聊一聊看似简单的Promise.prototype.then()方法
Promise.prototype.then()
Proise实例的then方法是定义在原型对象Promise.prototype上的,它的作用是为Promise实例添加状态改变时的回调函数。
该方法可以接收两个回调函数作为参数,其中第二个回调函数是可选的。第一个回调函数是 Promise 对象的状态变为 Resolved 时调用,第二个回调函数是 Promise 对象的状态变为 Rejected 时调用。
下面从以下几点进行说明:
then 方法返回的是一个Promise实例,但是需要注意的是并不是原来调用它的那个Promise实例而是一个新的Promise实例。
下面用代码来说明:
let promise = new Promise( function (resolve, reject) { resolve(); console.log("promise"); }); let promise_then = promise.then(function () { console.log("promise_then"); }); promise_then.then(function () { console.log("promise_then_then") }) // 运行结果: promise promise_then promise_then_then最先打印出
promise的原因是then方法的回调函数要在所有同步任务执行完后再执行,所以会先执行console.log("promise")然后再去执行下面then方法的回调函数。当程序执行到第6行结束时,
promise和promise_then的状态如下图所示:

可见then方法返回的是一个新的promise实例,并且此时promise_then的状态为
pending。当执行完第8行时,
promise和promise_then的状态如下图所示:

可见此时promise_then的状态变为resolved,也就是说只要then方法中的程序正常执行完不报错,返回实例的状态就变为resolved(这个地方原因不是很清楚,如果有明白的,欢迎留言告知,谢谢哦)。这个时候再往下执行
promise_then.then就会打印出promise_then_then。上面的代码等价于
// ES5写法 let promise = new Promise( function (resolve, reject) { resolve(); console.log("promise"); }); promise.then(function () { console.log("promise_then"); }).then(function () { console.log("promise_then_then") }); // ES6写法 let promise = new Promise( (resolve, reject) => { resolve(); console.log("promise"); }); promise.then( () => console.log("promise_then") ).then( () => console.log("promise_then_then") );then 方法中前一个回调函数的返回值可以传递给下一个回调函数。
- 前一个回调函数的返回值是一个非promise实例时,比较简单,看一下下面的代码就很容易理解。
let promise = new Promise( function (resolve, reject) { resolve(); }); promise.then(function () { return "aaa"; }).then(function (data) { console.log(data); }); // 输出结果 "aaa"当前一个回调函数的返回值是一个promise实例时,下一个then方法的执行情况要根据这个promise实例的状态来执行。
用下面的代码来解释一下:
// 如果形参是'Resolved' -> 状态为‘Resolved’的promise实例 // 如果形参是'Rejected' -> 状态为‘Rejected’的promise实例 function createPromise(status) { var p = new Promise(function (resolve, reject) { if (status === "Resolved") { resolve() } else { reject(); } }); return p; } createPromise("Resolved").then(function () { return createPromise("Rejected"); // 返回的promise实例的状态是“Rejected” }).then(function () { console.log("前一个回调函数的返回值promise实例的状态是'Resolved'"); }, function () { console.log("前一个回调函数的返回值promise实例的状态是'Rejected'"); }); // 输出结果 "前一个回调函数的返回值promise实例的状态是'Rejected'" createPromise("Resolved").then(function () { return createPromise("Resolved"); // 返回的promise实例的状态是“Resolved” }).then(function () { console.log("前一个回调函数的返回值promise实例的状态是'Resolved'"); }, function () { console.log("前一个回调函数的返回值promise实例的状态是'Rejected'"); }); // 输出结果: "前一个回调函数的返回值promise实例的状态是'Resolved'"根据上面代码的输出结果可以清晰地看到后一个回调函数的执行情况是根据前一个回调函数返回的promise的状态来执行的,如果返回的promise实例的状态为
Resolved,那么就执行第一个函数,如果返回的promise实例的状态为Rejected,那么就执行第二个函数。
完
如果不恰当之处,欢迎指正哦 _ 。
聊一聊看似简单的Promise.prototype.then()方法的更多相关文章
- promise(3) '静态'方法
要是人没有梦想,跟咸鱼又有什么两样了?一直恐惧读源码,哪怕是一个简单的库也是读百来行遇到难点就放弃了.对于新的东西也仅仅是知道它拿来干什么,社区资源在哪里,要用时就突击文档资源使用即可.未有过深入之心 ...
- es6语法中promise的使用方法
Promise是一个构造函数,它有resolve,reject,race等静态方法;它的原型(prototype)上有then,catch方法,因此只要作为Promise的实例,都可以共享并调用Pro ...
- 简单的 Promise 实现
参考 http://www.tuicool.com/articles/RzQRV3 var PENDING = undefined, FULLFILLED = 1, REJECTED = 2; var ...
- Promise (2) 基本方法
"I'm Captain Jack Sparrow" 加勒比海盗5上映,为了表示对杰克船长的喜爱,昨天闪现了几次模仿船长的走路姿势(哈哈哈,简直妖娆). 为了周天能去看电影,要赶紧 ...
- 实现简单的promise
只考虑成功时的调用,方便理解一下promise的原理promise的例子: 1. 接下来一步步实现一个简单的promise step1:promise 接受一个函数作为构造函数的参数,是立即执行的,并 ...
- 浅析 JavaScript 中的 Function.prototype.bind() 方法
Function.prototype.bind()方法 bind() 方法的主要作用就是将函数绑定至某个对象,bind() 方法会创建一个函数,函数体内this对象的值会被绑定到传入bind() 函数 ...
- 如何用原生JS实现一个简单的promise
我又又又回来了,最近真是累的跟狗一样,急需一个大保健回复一下子精力 我现在是一边喝着红牛一边写着博客,好了好了,不扯了,回归整体好吧 先简单来说一下啥是promise吧 它是什么?Promise是一个 ...
- JavaScript 中的 Function.prototype.bind() 方法
转载自:https://www.cnblogs.com/zztt/p/4122352.html Function.prototype.bind()方法 bind() 方法的主要作用就是将函数绑定至某个 ...
- 为Promise添加finally方法支持,把小程序函数变成promise函数
// 为Promise添加finally方法支持 Promise.prototype.finally = function (callback) { let P = this.constructo ...
随机推荐
- mysql的属性zerofill
一.字段中zerofill属性的类似定义方式 SQL语句:字段名 int(M) zerofill 二.zerofill属性的作用 1.插入数据时,当该字段的值的长度小于定义的长度时,会在该值的前面补上 ...
- windows 10上源码编译dlib教程 | compile dlib on windows 10
本文首发于个人博客https://kezunlin.me/post/654a6d04/,欢迎阅读! compile dlib on windows 10 Series Part 1: compile ...
- 【01】主函数main
java和C#非常相似,它们大部分的语法是一样的,但尽管如此,也有一些地方是不同的. 为了更好地学习java或C#,有必要分清它们两者到底在哪里不同. 首先,我们将探讨主函数main. java的主函 ...
- SCAU-1078 破密-数学的应用
另外一种方法和该题的题目在这位大佬的博客里 SCAU 1078 破密 还可以参考 https://blog.csdn.net/sinat_34200786/article/details/78 ...
- docker容器访问宿主机的IP——以rocketmq管理工具为例
在宿主机(MacOS系统)上运行了原生的RocketMQ服务,为了方便管理,需要以Docker方式运行RocketMQ的管理工具——rocketmq-console (项目地址:https://git ...
- ExtentTestNGIReporterListener
package com.testng.config; import com.aventstack.extentreports.ExtentReports; import com.aventstack. ...
- Fragment事务管理源码分析
转载请标明出处:http://blog.csdn.net/shensky711/article/details/53132952 本文出自: [HansChen的博客] 概述 在Fragment使用中 ...
- Spring(Bean)2
<!-- util:list封装的心 --> <bean id="personList2" class="spring.beans.di.collect ...
- 【Android - IPC】之ContentProvider简介
1.Content Provider简介 Content Provider是Android中提供的一种专门用于不同应用之间进行数据共享的方式,从这一点来看,它天生就适合IPC(Inter-Proces ...
- SpringBoot 整合mongoDB并自定义连接池
SpringBoot 整合mongoDB并自定义连接池 得力于SpringBoot的特性,整合mongoDB是很容易的,我们整合mongoDB的目的就是想用它给我们提供的mongoTemplate,它 ...