我正在研究Promise()构造函数,我注意到了一些适合我的unexpected.

console.log('first');
const promise1 = new Promise((resolve, reject) => {
  console.log('inside executor');
  let what = 1
  console.log(what());
  console.log('not reached');
  resolve('Hi Guys!');
});
console.log('continues'); // why does it continue?

输出:

first
inside executor
continues // whaaaaaaaaaaaaaaaaaaaaaaaat?????????
index.js:5 Uncaught (in promise) TypeError: what is not a function
  at index.js:5:15
  at new Promise (<anonymous>)

预期输出(I expect this output as the 100 runs synchronously):

first
inside executor
index.js:5 Uncaught (in promise) TypeError: what is not a function
      at index.js:5:15
      at new Promise (<anonymous>)

构造函数的executor据说运行synchronously,因此:

如果它应该是stop the execution of the script after each exception(在console.log(what();之后),为什么它会记录continues

我知道我应该用catch()来表示拒绝promise ,但这不是问题的重点.

推荐答案

如果它应该在每个异常之后(在console.log(what();)之后)停止执行脚本,为什么它会记录"继续"?

回调函数中发生的错误将由内部Promise实现为caught(这是called您的回调的部分),并将Promise的状态设置为Rejected.回调的执行真的会中断,正如运行时错误所预期的那样.但是,当错误被捕获(处理)时,调用者将从new Promise()调用中获得Promise对象,并且执行可以愉快地继续,并且打印"继续".

请参阅ECMAScript规范,其中executor是触发错误的回调函数:

  1. completion为完成(Call(executor,undefined,?resolvingFunctions.[[Resolve]],resolvingFunctions.[[Reject]]?)).
  2. 如果completion是一个突然的结束,那么
    a.执行?调用(resolvingFunctions.[[Reject]],undefined,«completion.[[Value]]»).
  3. 返还promise美元.

错误的处理发生在步骤10中:注意该过程如何不进一步传播该错误,而是注册一个拒绝并继续步骤11,这是一个正常的完成.

我们可以想象内部Promise构造函数代码看起来有点像这样(如果它是用JavaScript编写的),但经过简化:

class Promise {
    #state
    #resolvedValue
    #customers

    constructor(executor) {
        // ... initialisation code ...
        this.#state = "pending";
        this.#customers = []; // Any `then`, `catch` calls would populate this
        //       ...
        try {
             executor((value) => this.#resolve(value), 
                      (reason) => this.#reject(reason));
        } catch(err) {
             // Absorb the error, and allow execution to continue
             this.#reject(err); 
        }
    }

    #reject(reason) {
        if (this.#state !== "pending") return; // Ignore
        this.#state = "rejected";
        this.#resolvedValue = reason;
        // Queue the asynchronous calls of any then/catch callbacks 
        //    if they exist (registered in this.#customers)
        this.#broadcast(); // I omit the implementation
    }

    // ... define #resolve, then, catch, #broadcast, ...
    // ...
}

Javascript相关问答推荐

如何从defineExpose访问数据和方法

fetch在本地设置相同来源的cookie,但部署时相同的代码不会设置cookie

Vue:ref不会创建react 性属性

zoom svg以适应圆

调用removeEvents不起作用

在Angular中将样式应用于innerHTML

在我的html表单中的用户输入没有被传送到我的google表单中

如何避免页面第一次加载时由于CSS样式通过JavaScript更改而出现闪烁

Angular 订阅部分相互依赖并返回数组多个异步Http调用

ChartJs未呈现

环境值在.js文件/Next.js中不起作用

将数组扩展到对象中

当我try 将值更改为True时,按钮不会锁定

向数组中的对象添加键而不改变原始变量

自定义确认组件未在vue.js的v菜单内打开

警告框不显示包含HTML输入字段的总和

将相关数据组合到两个不同的数组中

构建器模式与参数对象输入

如何使用Reaction路由导航测试挂钩?

如何在Reaction中设置缺省值, Select 下拉列表,动态追加剩余值?