Skip to content

必须知道的 Promise 进阶点(一) #18

@spivet

Description

@spivet

本文不对 Promise 的基本用法和 API 做介绍,只是对一些进阶用法做总结。

异步函数中抛出的错误,无法被 catch

很多文章里都会说 reject() 与 throw 效果一样,这种说法并不完全正确。

如果在同步操作里用 throw 抛出错误,两者效果相同,但是如果在异步函数中抛出的错误,是无法被 catch 到的。

举个例子:

new Promise(function(resolve, reject) {
    setTimeout(function() {
        throw 'Uncaught Exception!'
    }, 100)
})
.catch(function(err) {
    console.log('打印错误', err) // 不会执行
})

这段代码会抛出错误,但是 catch 函数里的代码并不会执行,换作 reject 则可以:

new Promise(function(resolve, reject) {
    setTimeout(function() {
        reject('Caught Exception!')
    }, 100)
})
.catch(function(err) {
    console.log('打印错误', err) // 打印错误 Caught Exception!
})

用 .catch() 捕获异常

.catch() 的作用与 then(resolved, rejected) 中 rejected 回调的作用几乎一致。但是 resolved 回调里抛出的错误在 rejected 是无法捕获的,所以尽量使用 .catch() 来进行错误捕获。

.then() 回调函数的返回值

在 .then() 的回调函数里通常会返回三种类型的值:

1. return 另一个 promise

var anotherPromise = function() {
    return Promise.resolve('bar')
}

Promise.resolve('foo')
    .then(function(value) {
        console.log(value) // foo
        return anotherPromise()
    })
    .then(function(result) {
        console.log(`result is: ${result}`) // result is: bar
    })

2. return 一个同步的值 (如果没有明确返回值,会默认返回 undefined)

var anotherPromise = function() {
    return Promise.resolve('bar')
}

Promise.resolve('foo')
    .then(function(value) {
        console.log(value) // foo
        anotherPromise()
        return '同步值'
    })
    .then(function(result) {
        console.log(`result is: ${result}`) // result is: 同步值
    })

Promise.resolve('foo')
    .then(function(value) {
        anotherPromise()
    })
    .then(function(result) {
        console.log(`result is: ${result}`) // result is: undefined
    })

3. throw 一个同步异常(不是返回值,但在这里把它当作返回值)

var anotherPromise = function() {
    throw 'oh error!'
}

Promise.resolve('foo')
    .then(function(value) {
        return anotherPromise()
    })
    .catch(function(err) {
        console.log(`result is: ${err}`) // result is: oh error!
    })

Promise 穿透

.then(resolved, rejected) 中的参数 resolved rejected 必须是两个回调函数。

假如传的不是函数,而是直接调用函数,那么上一个 Promise 返回的值会跳过这个 then,直接到下一个。

function sayHello() {
	console.log('hello')
}

console.log('start')

Promise.resolve('foo')
    .then(sayHello())
    .then(function(result) {
        console.log(`result is: ${result}`)
    })

console.log('end')

// 会依次打印
start
hello
end
result is: foo

参考文章

Promise进阶
We have a problem with promises
Promise - JavaScript | MDN

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions