JS中Promise函数then的奥秘探究


Posted in Javascript onJuly 30, 2018

Promise概述

Promise对象是CommonJS工作组提出的一种规范,目的是为异步操作提供统一接口。

那么,什么是Promises?

首先,它是一个对象,也就是说与其他JavaScript对象的用法,没有什么两样;其次,它起到代理作用(proxy),充当异步操作与回调函数之间的中介。它使得异步操作具备同步操作的接口,使得程序具备正常的同步运行的流程,回调函数不必再一层层嵌套。

简单说,它的思想是,每一个异步任务立刻返回一个Promise对象,由于是立刻返回,所以可以采用同步操作的流程。这个Promises对象有一个then方法,允许指定回调函数,在异步任务完成后调用。

Promise的then方法可以接受前一个函数的执行结果,还可以保证另一个Promise的顺序执行,这到底是怎么做到的呢?

原理图(先上图)

JS中Promise函数then的奥秘探究

问题需求

如何保证多个 promise 顺序执行?

实例:

var f1 = function (){
 return new Promise(function (resolve, reject){
  setTimeout(function (){
   console.log("f1 ok!")
   resolve("f1 ok!");
  }, 1000)
 });
}
var f2 = function (){
 return new Promise(function (resolve, reject){
  setTimeout(function (){
   console.log("f2 ok!")
   resolve("f2 ok!");
  }, 3000)
 });
}
var f3 = function (){
 return new Promise(function (resolve, reject){
  setTimeout(function (){
   console.log("f3 ok!")
   resolve("f3 ok!");
  }, 2000)
 });
}

当然如果要并行的话,我们很容易想到 Promise.all 方法:

Promise.all([f1(), f2(), f3()]).then(function (data){
 console.log(data)
})
// f1 ok! 
// f3 ok! 
// f2 ok! 
// ["f1 ok!", "f2 ok!", "f3 ok!"]

如果要顺序执行:

f1().then(f2).then(f3)
// f1 ok!
// f2 ok!
// f3 ok!

//或者这样

function f(all) {
 var promise = Promise.resolve();
 all.forEach((p, index) => {
  promise = promise.then(p)
 })
}
f([f1, f2, f3])

那么问题来了,then是如何做到顺序执行的呢,参数既可以是一个普通函数,也可是是一个返回promise的函数?

then的奥秘

很多实现promise的库都比较复杂,如果自己实现的话,可以借鉴下面简单的代码:

Promise.prototype.then = function(onFulfilled, onRejected) {
 var promise = this;
 return new Promise(function(resolve, reject) {
  function handle(value) {
   var ret = typeof onFulfilled === 'function' && onFulfilled(value) || value;
   if (ret && typeof ret['then'] == 'function') {
    ret.then(function(value) {
     resolve(value);
    }, function(reason) {
     reject(reason);
    });
   } else {
    resolve(ret);
   }
  }
  function errback(reason) {
   reason = typeof onRejected === 'function' && onRejected(reason) || reason;
   reject(reason);
  }
  if (promise._status === 'PENDING') {
   promise._resolves.push(handle);
   promise._rejects.push(errback);
  } else if (promise._status === FULFILLED) { 
   callback(promise._value);
  } else if (promise._status === REJECTED) {
   errback(promise._reason);
  }
 });
}

重点在then的实现,看上述代码,每个then返回的是什么,是一个新的 Promise,一个新的 Promise,一个新的 Promise
第二个重点是,在内部又处理了一个 回调函数运行结果是 一个 promise的 判断,如果是那么等待这个promise运行结束才调用 resolve 更改状态,关键是resolve的调用时机,resolve的调用时机,才能够往下执行,这两步就是then函数的关键。
是不是 有点晕,请看最开始的图。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
Javascript笔记一 js以及json基础使用说明
May 22 Javascript
jquery数组过滤筛选方法grep()简介
Jun 06 Javascript
AngularJS入门教程之学习环境搭建
Dec 06 Javascript
Bootstrap模态框禁用空白处点击关闭
Oct 20 Javascript
JS动态的把左边列表添加到右边的实现代码(可上下移动)
Nov 17 Javascript
javascript 封装Date日期类实例详解
May 28 Javascript
vue.js评论发布信息可插入QQ表情功能
Aug 08 Javascript
Three.js入门之hello world以及如何绘制线
Sep 25 Javascript
Vue项目中添加锁屏功能实现思路
Jun 29 Javascript
Vue.js项目实战之多语种网站的功能实现(租车)
Aug 07 Javascript
JS this关键字在ajax中使用出现问题解决方案
Jul 17 Javascript
Vue实现boradcast和dispatch的示例
Nov 13 Javascript
浅析java线程中断的办法
Jul 29 #Javascript
还不懂递归?读完这篇文章保证你会懂
Jul 29 #Javascript
如何在js代码中消灭for循环实例详解
Jul 29 #Javascript
Vue-cli3项目配置Vue.config.js实战记录
Jul 29 #Javascript
vue权限路由实现的方法示例总结
Jul 29 #Javascript
JS高级技巧(简洁版)
Jul 29 #Javascript
js运算符的一些特殊用法
Jul 29 #Javascript
You might like
德生PL990的分析评价
2021/03/02 无线电
使用eAccelerator加密PHP程序
2008/10/03 PHP
iis下php mail函数的sendmail配置方法(官方推荐)
2012/04/25 PHP
CI框架整合smarty步骤详解
2016/05/19 PHP
PHP静态成员变量
2017/02/14 PHP
php+ajax实现文件切割上传功能示例
2020/03/03 PHP
JQuery 文本框使用小结
2010/05/22 Javascript
基于jQuery的淡入淡出可自动切换的幻灯插件打包下载
2010/09/15 Javascript
jquery load事件(callback/data)使用方法及注意事项
2013/02/06 Javascript
封装html的select标签的js操作实例
2013/07/02 Javascript
js中的preventDefault与stopPropagation详解
2014/01/29 Javascript
javascript setinterval 的正确语法如何书写
2014/06/17 Javascript
JavaScript知识点总结(十六)之Javascript闭包(Closure)代码详解
2016/05/31 Javascript
深入理解javascript作用域第二篇之词法作用域和动态作用域
2016/07/24 Javascript
JS实现生成由字母与数字组合的随机字符串功能详解
2018/05/25 Javascript
如何自动化部署项目?折腾服务器之旅~
2019/04/16 Javascript
微信小程序上传图片到php服务器的方法
2019/05/23 Javascript
vue.js 子组件无法获取父组件store值的解决方式
2019/11/08 Javascript
关于AngularJS中几种Providers的区别总结
2020/05/17 Javascript
Vue如何循环提取对象数组中的值
2020/11/18 Vue.js
Python内置的字符串处理函数详细整理(覆盖日常所用)
2014/08/19 Python
Python连接mssql数据库编码问题解决方法
2015/01/01 Python
Python contextlib模块使用示例
2015/02/18 Python
对pandas处理json数据的方法详解
2019/02/08 Python
使用python serial 获取所有的串口名称的实例
2019/07/02 Python
django最快程序开发流程详解
2019/07/19 Python
Python判断三段线能否构成三角形的代码
2020/04/12 Python
css3之UI元素状态伪类选择器实例演示
2017/08/11 HTML / CSS
IE滤镜与CSS3效果(详细整理分享)
2013/01/25 HTML / CSS
酒店工作职员求职简历的自我评价
2013/10/23 职场文书
2014和解协议书范文
2014/09/15 职场文书
国际残疾人日广播稿范文
2014/10/09 职场文书
2015年农村党员干部主题教育活动总结
2015/03/25 职场文书
公文格式,规则明细(新手收藏)
2019/07/23 职场文书
导游词之秦皇岛燕塞湖
2020/01/03 职场文书
用Python提取PDF表格的方法
2021/04/11 Python