通俗浅显的理解Promise中的then

Promise,ES6中定义的规范,不会使用Promise,都不敢说自己用过ES6,大部分介绍Promise的规范的文章对于新手小白来说看得云里雾里,且并不是通俗易懂。本文通过实例介绍讲述Promise中then的的最通俗应用理解,代码建立在不出现异常的情况的操作下,不严谨之处,请以官方规范为标准。

先看一下下面4个Promise到底有什么区别呢?

func().then(function () {
  return cb();
});
 
func().then(function () {
  cb();
});
 
func().then(cb());
 
func().then(cb);

如果你知道答案,以下内容你可以不用继续。

上面的代码过于简单,运行时话需要稍微进行一点扩展,每个方法中都打印出promise上一步的调用值,为了方便我给每个方法加了一个下标输出,分别是1、2、3、4。

let func = function() {
    return new Promise((resolve, reject) => {
        resolve('返回值');
    });
};

let cb = function() {
    return '新的值';
}

func().then(function () {
    return cb();
}).then(resp => {
    console.warn(resp);
    console.warn('1 =========<');
});

func().then(function () {
    cb();
}).then(resp => {
    console.warn(resp);
    console.warn('2 =========<');
});

func().then(cb()).then(resp => {
    console.warn(resp);
    console.warn('3 =========<');
});

func().then(cb).then(resp => {
    console.warn(resp);
    console.warn('4 =========<');
});

不卖关子,直接看结果

clipboard.png

首先要明白Promise中then方法会干什么事情!

官方文档是这样定义的:

一个 promise 必须提供一个 then 方法以访问其当前值、终值和据因。

promise 的 then 方法接受两个参数:

promise.then(onFulfilled, onRejected) Todo:这里只介绍onFulfilled,所以删除了关于onRejected的规范定义

onFulfilled 和 onRejected 都是可选参数。

如果 onFulfilled 不是函数,其必须被忽略
如果 onFulfilled 是函数:

当 promise 执行结束后其必须被调用,其第一个参数为 promise 的终值
在 promise 执行结束前其不可被调用
其调用次数不可超过一次

用通(ren)俗(hua)的话来说:
then方法提供一个供自定义的回调函数,若传入非函数,则会忽略当前then方法。
回调函数中会把上一个then中返回的值当做参数值供当前then方法调用。
then方法执行完毕后需要返回一个新的值给下一个then调用(没有返回值默认使用undefined)。
每个then只可能使用前一个then的返回值。

直观的图:
clipboard.png

有了上面的定义我们带着三个疑问来回答问题:

  1. 上一个then中传入了回调函数吗?
  2. 上一个then中提供了返回值吗?
  3. 若上一个then中若提供了返回值,返回了什么?

执行第一个方法:

func().then(function () {
    return cb();
}).then(resp => {
    console.warn(resp);
    console.warn('1 =========<');
});

clipboard.png

function () {
    return cb();
}

显而易见,是传入了回调函数的
回调函数中把cb执行后的返回值当做then中的返回值,所以输出了“新的值”;

执行第二个方法:

func().then(function () {
    cb();
}).then(resp => {
    console.warn(resp);
    console.warn('2 =========<');
});

clipboard.png

function () {
    cb();
}

then回调方法,只是执行了cb方法,并没有return值,定义中讲过若then没有返回值,提供给下一个then使用的参数就是undefined,所以打印出来的是undefined;

执行第三个方法:

func().then(cb()).then(resp => {
    console.warn(resp);
    console.warn('3 =========<');
});

clipboard.png

func().then(cb())

then中cb()执行后返回的并不是一个函数,在Promise规范中会自动忽略调当前then,所以会把func中的返回值供下一个then使用,输出了“返回值”

执行第四个方法:

func().then(cb).then(resp => {
    console.warn(resp);
    console.warn('4 =========<');
});

clipboard.png

func().then(cb)

第一个方法在回调内部返回cb执行后的值,第四个方法则直接把cb当做回调,第一个方法与第四个方法异曲同工之妙,所以也输出了“新的值”。

题目出处:http://web.jobbole.com/82601/
Promise规范:https://promisesaplus.com/


你还没有成为真正的孙悟空,是因为你还没有遇见那个给你脚底三颗痣的人~

651 声望
11 粉丝
0 条评论
推荐阅读
哈希摘要算法
最近在看一些NPM库的时候总是看到各种哈希签名算法,之前工作中也有用到过签名算法,但并没有深入理解过其中的原理,于是找了点资料稍微了解了一下,总结了这篇文章。

petruslaw4阅读 3.7k

基于promise的阻塞式队列设计
设计阻塞队列的缘由是因为在做业务时遇见庞大的资源列表加载问题,我们的业务主要是媒体资源的加载。http 1.0的时候大部分浏览器支持最大并行数量是6个,http 2.0的时候有所提升,HTTP/2.0理论上可以在一个TCP连...

H_H_code3阅读 1.6k

CSS新规范:样式查询
微信搜索 【大迁世界】, 我会第一时间和你分享前端行业趋势,学习途径等等。本文 GitHub [链接] 已收录,有一线大厂面试完整考点、资料以及我的系列文章。

前端小智2阅读 799

深入理解JavaScript——继承
JavaScript 的继承是基于原型实现,在前文 原型 里,笔者讲到了原型继承,并详细介绍了显式原型继承和隐式原型继承各自的两种方法。现在我们以继承的视角切入,并以案例的形式来介绍 8 种常见的 JavaScript 继承方法

山头人汉波2阅读 967

Promise: 异步编程的理解和使用
JavaScript 中,Promise 的流行是得益于 jQuery 的方法 jQuery.Deferred(),其他也有一些更精简独立的 Promise 库,例如:Q、When、Bluebird。

后除2阅读 902

百万并发场景中倒排索引与位图计算的实践
Promise时效控单系统作为时效域的控制系统,在用户下单前、下单后等多个节点均提供服务,是用户下单黄金链路上的重要节点;控单系统主要逻辑是针对用户请求从规则库中找出符合条件的最优规则,并将该规则的时效控...

京东云开发者1阅读 476

封面图
TypeScript系列:【3】类
基础说明先来看个例子: {代码...} 这样,我们就定义了一个类,包含一个属性用于保存名称,一个构造器用于创建的时候设置名称,方法say用于获取名称描述: {代码...} 打印的结果就是:“你好,我是小强”。公共,私...

zxl200707011阅读 826

你还没有成为真正的孙悟空,是因为你还没有遇见那个给你脚底三颗痣的人~

651 声望
11 粉丝
宣传栏