Promise中then的链式回调

看题!

new Promise((resolve, reject) => {
            reject(1); // 确定promise状态为rejected
        }).then((fullfilled) => {
            console.log(fullfilled);
        }, (rejected) => {
            console.log(rejected, '2-1'); // 执行这里,then方法必须返回一个新的Promise实例,这个没有明式 return 值,便隐式触发新promise的fullfilled状态,进入下一个then的fullfilled回调
        }).then((fullfilled) => {
            console.log(fullfilled, '3-1'); // 执行这里,因上一步resolve未传值,所以fullfilled为undefined,继续隐式触发fullfilled回调
        }, (rejected) => {
            console.log(rejected, '3-2');
        }).then((fullfilled) => {
            console.log(fullfilled, '4-1'); // 执行这里
            return Promise.reject(5); // 明式返回rejected的promise
        }, (rejected) => {
            console.log(rejected, '5-1');
        }).catch((error) => {
            console.log(error, '6-1'); // 执行这里,被catch捕获,error为上一步reject传入的值。因Promise.prototype.catch方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数,所以catch同样返回一个新的promise,若没有显示指定,便同上执行隐式操作
        }).then(fullfilled => {
            console.log(fullfilled, '7-1'); // 执行这里
        }, rejected => {
            console.log(rejected, '7-2');
        })

结果为:

1 "2-1"
undefined "3-1"
undefined "4-1"
5 "6-1"
undefined "7-1"

总结:

  1. Promise.prototype.then()返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
  2. then方法中若有显式 return 一个新的 promise(包括fullfilled和rejected)则显示执行。若无显式指定,则隐式触发新promise的pending->fullfilled状态变更,进入下一个thenfullfilled回调。
  3. Promise.prototype.catch()方法是.then(null, rejection).then(undefined, rejection)的别名,用于指定发生错误时的回调函数,所以catch同样返回一个新的promise,若没有显示指定,便执行隐式操作。

建议:

  • 不要在then方法里面定义 Reject 状态的回调函数(即then的第二个参数),总是使用catch方法。

以上留有歧义者欢迎指出!

参考资料:
PromiseA+ 规范地址
中文翻译PromiseA+ 规范
解读Promise内部实现原理

这里也结合promise提一下 event loop,JavaScript执行流程由函数调用栈与异步队列(宏任务与微任务组成)。

注意这里 macrotask microtask 分别表示异步任务的两种分类。js运行过程中,JS 引擎会将所有任务按照类别分到两个队列中,首先在 macrotask 的队列(也叫 task queue)中取出第一个任务,执行完毕后取出 microtask 队列中的所有任务顺序执行;之后再取 macrotask 任务,周而复始,直至两个队列的任务都取完。(任务的执行都是在函数调用栈中完成的)。

上一个例子:

console.log('start');
setImmediate(() => {
  console.log(1);
  new Promise((resolve, reject) => {
    resolve(4);
  }).then((data) => {
    console.log(data);
  })
});
setTimeout(() => {
  console.log(2);
});
new Promise((resolve, reject) => {
  resolve(3);
}).then((data) => {
  console.log(data);
})
console.log('end');

结果:

start
end
3
1
4
2

其中chrome中,setImmediate优先于setTimeout执行

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值