javascript - 为什么这里错误不会被抛出?

查看:152
本文介绍了javascript - 为什么这里错误不会被抛出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

const promise = new Promise(function (resolve) {
    resolve('ok');
    // setTimeout(function () {
        throw new Error('test');
    // }, 0);
});

promise.then(console.log);

注释去掉之后则可以

解决方案

终于回到学校了...
题主所说的情况:

const promise = new Promise(function (resolve) {
    resolve('ok');
    // setTimeout(function () {
        throw new Error('test');
    // }, 0);
});

promise.then(console.log);

问题:不能抛出异常.

接下来我们多个情况分析并尝试解释下.

首先给大家抛个源码地址吧
传送门:https://github.com/then/promi...

function Promise(fn) {
  if (typeof this !== 'object') {
    throw new TypeError('Promises must be constructed via new');
  }
  if (typeof fn !== 'function') {
    throw new TypeError('Promise constructor\'s argument is not a function');
  }
  this._deferredState = 0;
  this._state = 0;
  this._value = null;
  this._deferreds = null;
  if (fn === noop) return;
  doResolve(fn, this);
}
//其中doResolve()中对抛出错误进行了处理并调用了相应resolve()/reject()函数来修改自身的状态和值/拒因

注释掉setTimeout的情况下,console.log出"ok"

  1. Promise函数中,doResolve其实与then函数中处理相似,都具有2点的特征,也就是一次性,所以在调用了resolve("ok")后,状态和值已经固定,并传给了then()

  2. then函数的问题,我们看看then函数是怎样的promise2 = promise1.then(onFulfilled, onRejected),传入onFulfilled,onRejected两个函数,返回一个promise对象.具体可以看我博文,现在我把题主传入函数对应的情况拿出来.

  • 如果onFulfilled不是函数且promise1状态为fulfilled,则promise2状态为fulfilled且值与promise1的值相同

  • 如果onRejected不是函数且promise1状态为rejected,那么promise2状态必须为rejected且与promise1的reason拒因相同.

  • onFulfilled和onRejected函数只能在promise状态为fulfilled/rejected时调用一次

我们可以看出promise传递给then,then只接受了onFulfilled函数,所以console中出现了"ok"

注释掉resolve("ok")和setTimeout,console无任何信息

new Promise(fn)中,为了让promise正常生成,在内部进行了错误的捕获,具体函数是这样的

function tryCallTwo(fn, a, b) {
  try {
    fn(a, b);
  } catch (ex) {
    LAST_ERROR = ex;
    return IS_ERROR;
  }
}

Promise把传入的fn函数进行了错误的捕获,并且返回IS_ERROR来表示出现了异常,在这个时候异常已经被捕获并处理了,然后根据这个异常我们的promise的状态也由pending->rejected,并且拥有了拒因 异常ex.

这个promise传递给了then函数,然而,我们的then函数中onRejected是undefined的,所以这个then函数直接返回了新的rejected并带有拒因 异常ex 的promise对象(then必须返回一个promise对象.)以其后续处理.

所以console中没有任何信息生成

不注释任何代码,直接执行,console中出现"ok"并接着抛出异常

出现"ok"的原因我们说清楚了,然后抛出异常就是因为setTimeout 0的作用了.
众所周知,JavaScript于浏览器端是单线程执行的,我们的任务是一个队列(event loop),所谓的延时,计时器,触发回调是都是基于计时器的,所谓触发执行其实都是立即排队而已.当setTimeout设置时间为0,也代表的是立即插入队列,不是立即执行,也不保证执行时间,所以这样setTimeout(fn,0)其实表示的不是立即执行,而是你排队吧,类似于将队伍第一个人扔到队尾去了.
所以异常其实是在执行完了promise构建后被抛出的,所以,就出现了console中出现"ok"并抛出异常的现象

其实这里我也不是很清楚,希望有人做个补充

这篇关于javascript - 为什么这里错误不会被抛出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆