我自己做了一些测试,发现 .then() 或 .catch() 中的错误处理程序不会捕获 Promise.resolve(value) 的“值”中的错误,但会在 Promise 构造函数中捕获它解析(值)。
我尝试了 Promise.resolve 和带有解析“值”的承诺构造函数,该构造函数会引发错误(尝试使用未定义的变量以及引发错误的外部函数)。两者都有 .then 和 .catch 跟随。
我想我知道在 Promise.resolve 中,'value' 在它被'发送'到 then 之前被评估 - 所以 JavaScript 会抛出一个异常并在它有机会被 .then 捕获之前关闭它或.catch。但是为什么在 promise 构造函数中的 resolve(value) 没有发生同样的情况。
只是为了澄清:
在以下情况下,JavaScript 报告未处理的异常并且一切停止:
Promise.resolve(someError)
.catch(() => {
console.error('This never gets printed');
})
但是……
在下面的情况下,.catch 确实会捕获错误并打印其消息:
new Promise ((resolve, reject) => {
resolve(someError)
})
.catch(() => {
console.error('This actually gets printed');
})
答案 0 :(得分:2)
Promise 构造函数行为
调用promise构造函数的语法是
Promise( executorFunction)
这导致 Promise
在返回构造的承诺之前同步调用带有两个函数参数的执行器函数。出于讨论目的,通常调用参数 resolve
和 reject
。
为了清理边缘情况,Promise
返回一个被拒绝的承诺,如果执行程序在调用其参数之一之前抛出,返回的承诺的拒绝原因设置为抛出的错误。另一方面,如果执行器同步调用 resolve
或 reject
并在之后继续抛出错误,则返回的承诺将根据调用的参数函数被解析或拒绝:抛出的错误将被忽略!
案例 1
Promise.resolve(someError)
.catch(() => {
console.error('This never gets printed');
})
在调用 Promise.resolve
方法之前,JavaScript 引擎会评估要传递给该方法的参数。如果使用语法或运行时错误评估 someError
错误,代码执行会因遇到错误而停止。 “一切都停止了”,不会调用 Promise.resolve
,也不会执行以下代码。
案例 2
new Promise ((resolve, reject) => {
resolve(someError)
})
.catch(() => {
console.error('This actually gets printed');
})
此处 someError
在执行器内部被评估为传递给 resolve
的参数。由于它出错,JavaScript 引擎从不调用 resolve
。但是对于执行程序提前抛出的情况,Promise
的定义行为是返回一个被拒绝的承诺,原因设置为抛出的错误。稍后调用的 .catch
子句并打印“这实际上被打印了”;
标准(永久链接)
如果执行程序抛出异常,ECMA Script 2015 (“ES6”) 标准要求构造函数调用 25.4.3.1 部分第 10 步中返回的 promise 的 reject
函数。但是,如果 Promise 已被同步解析或拒绝,则这不会影响它的状态:如果之前已调用过对 resolve
/reject
函数的其他调用,则会被静默忽略。>