promise 拙见
一,promise是什么?
promise 是最早由社区提出和实现是一种解决异步编程的方案,比其他传统的解决方案(回调函数和事件)更合理和强大。
ES6 将其写进了语言标准,统一了用法,原生提供了 promise 对象。
ES6 规定,promise对象是一个构造函数,用来生成 promise 实例。
二,promise是为解决什么问题而产生的?
promise是为解决异步处理回调金字塔问题而产生的
三,promise的两个特点
1,promise对象的状态不受外界影响
a,pending 初始状态
b,fulfilled 成功状态
c,rejected 失败状态
promise 有以上三种状态,只有一步操作的结果可以解决当前是哪一种状态,其他任何操作都无法改变这种状态;
2,promise 的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆,只能由pending 变成fulfilled 或者pending 变成 rejected
四,promise的三个缺点
1,无法取消promise,一旦新建它就会立即执行,无法中途取消
2,如果不设置回调函数,promise 内部抛出的错误,不会反映到外部
3,当处于 pending 状态时,无法得知目前进展到了哪一个阶段,是刚刚开始还是即将完成
五,promise在哪存放成功回调序列和失败回调序列?
1,onResolvedCallbacks 成功后要执行的回调序列 是一个数组
2,onResolvedCallbacks 失败后要执行的回调序列 是一个数组
以上两个数组存放在promise 创建实例时给promise这个类传的函数中,默认都是空数组。
每次实例 then 的时候 传入onFulfilled 成功回调 onRejected 失败回调,如果此时的状态是pending 则将onFulfilled 和 onRejected push 到对应的成功回调序列数组和失败回调序列数组中,如果此时的状态是fulfilled 则 onFulfilled 立即执行,如果此时的状态是rejected 则 onRejected 立即执行
上述序列中的回调函数执行的时候 是有顺序的,即按照顺序依次执行
六,promise的用法
1,promise 构造函数接受一个函数作为参数,该函数的两个参数分别是resolve 和 reject。它们是两个函数,由JavaScript 引擎提供,不用自己部署。
const promise = new Promise(function(resolve, reject) {
// ... some code if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
2,resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
3,Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
promise.then(function(value) {
// success
}, function(error) {
// failure
});
then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。
七、按照Promise A+规范写Promise的简单实现原理
// 第一步:Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
function Promise(task) { let that = this; // 缓存this
that.status = 'pending'; // 进行中的状态
that.value = undefined; //初始值 that.onResolvedCallbacks = []; // 存放成功后要执行的回调函数的序列
that.RejectedCallbacks = []; // 存放失败后要执行的回调函数的序列
// 该方法是将Promise由pending变成fulfilled
function resolve (value) {
if (that.status == 'pending') {
that.status = 'fulfilled';
that.value = value;
that.onResolvedCallbacks.forEach(cb => cd(that.value))
} }
// 该方法是将Promise由pending变成rejected
function reject (reason) {
if (that.status == 'pending') {
that.status = 'rejected';
that.value = reason;
that.onRjectedCallbacks.forEach(cb => cd(that.value))
}
} try {
// 每一个Promise在new一个实例的时候 接受的函数都是立即执行的
task(resolve, reject)
} catch (e) {
reject(e)
}
} // 第二部 写then方法,接收两个函数onFulfilled onRejected,状态是成功态的时候调用onFulfilled 传入成功后的值,失败态的时候执行onRejected,传入失败的原因,pending 状态时将成功和失败后的这两个方法缓存到对应的数组中,当成功或失败后 依次再执行调用
Promise.prototype.then = function(onFulfilled, onRejected) {
let that = this;
if (that.status == 'fulfilled') {
onFulfilled(that.value);
}
if (that.status == 'rejected') {
onRejected(that.value);
}
if (that.status == 'pending') {
that.onResolvedCallbacks.push(onFulfilled);
that.onRjectedCallbacks.push(onRejected);
}
}
八、Promise 链式写法
我们先来看一个例子,根据例子得出结论,然后再写源码的实现部分来验证结论
let promise = new Promise(function (resolve, reject) {
resolve(100);// reject(100)
}); promise.then(function (data) {
return data+100; },function (err) {
return 'ssss'; }).then(function (data) {
console.log(data);// 200 // undefined // sss
})
从上面的例子可以看出:
当第一个promise的成功的回调里返回 200时,第二个promise的成功回调的参数就是200,当将resolve(100)改成reject(100)的时候,因为失败回调中什么也没有返回所以第二个promise的成功回调中的参数是undefined,当失败的回调中返回sss时,第二个promise的成功回调中的参数是sss,由此我们可以看出,第一个promise不管成功回调还是失败回调,他的返回值作为第二个promise中的成功时回调函数的参数值,链式写法能一直then下去的原因:链式调用靠的是返回新的promise,来保证可以一直走成功或失败
九、 Promise.catch
Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。
//catch原理就是只传失败的回调
Promise.prototype.catch = function(onRejected){
this.then(null,onRejected);
}
十、 Promise.all 方法
参数:接受一个数组,数组内都是Promise实例
返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中所有的实例都处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态
Promise.all = function(promises){
return new Promise(function(resolve,reject){
let done = gen(promises.length,resolve);
for(let i=0;i<promises.length;i++){
promises[i].then(function(data){
done(i,data);
},reject);
}
});
}
十一、Promise.resolve
返回一个Promise实例,这个实例处于resolve状态。
根据传入的参数不同有不同的功能:
值(对象、数组、字符串等):作为resolve传递出去的值
Promise实例:原封不动返回
//返回一个立刻成功的promise
//别人提供 给你一个方法,需要你传入一个promise,但你只有一个普通的值,你就可以通过这个方法把这个普通的值(string number object)转成一个promise对象
Promise.resolve = function(value){
return new Promise(function(resolve){
resolve(value);
});
}
十二、 Promise.reject
返回一个Promise实例,这个实例处于reject状态。
参数一般就是抛出的错误信息。
//返回一个立刻失败的promise
Promise.reject = function(reason){
return new Promise(function(resolve,reject){
reject(reason);
});
}
十三、 Promise.race
参数:接受一个数组,数组内都是Promise实例
返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中任何一个实例处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态。
Promise.race = function(promises){
return new Promise(function(resolve,reject){
for(let i=0;i<promises.length;i++){
promises[i].then(resolve,reject);
}
});
}
promise 拙见的更多相关文章
- 实现Promise的first等各种变体
本篇文章主要是想通过ES6中Promise提供的几个方法,来实现诸如first.last.none.any等各种变体方法! 在标准的ES6规范中,提供了Promise.all和Promise.race ...
- Javascript - Promise学习笔记
最近工作轻松了点,想起了以前总是看到的一个单词promise,于是耐心下来学习了一下. 一:Promise是什么?为什么会有这个东西? 首先说明,Promise是为了解决javascript异步编 ...
- 路由的Resolve机制(需要了解promise)
angular的resovle机制,实际上是应用了promise,在进入特定的路由之前给我们一个做预处理的机会 1.在进入这个路由之前先懒加载对应的 .js $stateProvider .state ...
- angular2系列教程(七)Injectable、Promise、Interface、使用服务
今天我们要讲的ng2的service这个概念,和ng1一样,service通常用于发送http请求,但其实你可以在里面封装任何你想封装的方法,有时候控制器之间的通讯也是依靠service来完成的,让我 ...
- 闲话Promise机制
Promise的诞生与Javascript中异步编程息息相关,js中异步编程主要指的是setTimout/setInterval.DOM事件机制.ajax,通过传入回调函数实现控制反转.异步编程为js ...
- 深入理解jQuery、Angular、node中的Promise
最初遇到Promise是在jQuery中,在jQuery1.5版本中引入了Deferred Object,这个异步队列模块用于实现异步任务和回调函数的解耦.为ajax模块.队列模块.ready事件提供 ...
- Promise的前世今生和妙用技巧
浏览器事件模型和回调机制 JavaScript作为单线程运行于浏览器之中,这是每本JavaScript教科书中都会被提到的.同时出于对UI线程操作的安全性考虑,JavaScript和UI线程也处于同一 ...
- JavaScript进阶之路——认识和使用Promise,重构你的Js代码
一转眼,这2015年上半年就过去了,差不多一个月没有写博客了,"罪过罪过"啊~~.进入了七月份,也就意味着我们上半年苦逼的单身生活结束了,从此刻起,我们要打起十二分的精神,开始下半 ...
- 细说Promise
一.前言 JavaScript是单线程的,固,一次只能执行一个任务,当有一个任务耗时很长时,后面的任务就必须等待.那么,有什么办法,可以解决这类问题呢?(抛开WebWorker不谈),那就是让代码异步 ...
随机推荐
- WebDriver高级应用实例(7)
7.1在测试中断言失败的步骤进行屏幕截图 目的:在测试过程中,在断言语句执行失败时,对当前的浏览器进行截屏,并在磁盘上新建一个yyyy-mm-dd格式的目录,并在断言失败时新建一个已hh-mm-ss格 ...
- [原创]Chorme密码读取工具\Firefox密码读取工具
工具: getBrowserPWD编译: VC作者: K8哥哥博客: http://qqhack8.blog.163.com发布: 2017/11/24 16:16:17 简介: 有时为了方便我们会让 ...
- 使用webpack和react搭建项目
看了N多博客,日志,一边迷茫一边摸索.本文记录流程.我怕自己忘了...并且修复了博客园首页推荐那个日志中遇到的bug 1.webstorm新建一个空白项目,比如webpack_demo 2.因为要用r ...
- odoo开发笔记 -- odoo10 视图界面根据字段状态,动态隐藏创建&编辑按钮
场景描述: 解决方式: 网络搜索,vnsoft_form_hide_edit 找到了这个odoo8的模块, odoo10语法和视图界面有新的变化,所以需要修改一些地方,感兴趣的小伙伴可以对比下两个代码 ...
- MySQL笔记(4)---表
1.前言 上一章记录了MySQL中的一些文件组成,以及相关作用和参数配置,本章开始记录深层次的存储结构,以便更好理解MySQL的设计. 2.索引组织表 InnoDB中,表都是根据主键顺序组织存放的,这 ...
- ThreadPoolExecutor 中的 shutdown() 、 shutdownNow() 、 awaitTermination() 的用法和区别
Java并发编程中在使用到ThreadPoolExecutor时,对它的三个关闭方法(shutdown().shutdownNow().awaitTermination())的异同点如下: shutd ...
- 解析BroadcastReceiver之你需要了解的一些东东
前些天把四大组件之一的Service扯了一遍,今天就要开始谈谈它的弟兄BroadcastReceiver了.写到这里我挺纠结的,因为广播接收者确实比较简单,但是各位就不要以为简单的就不内涵,也许我们慢 ...
- Method 'initializationerror' not found.Opening the test classs JUnit4单元测试报错问题解决办法(图文详解)
不多说,直接上干货! 问题现象 今天使用JUnit 4进行单元测试时,测试程序一直运行不起来,报method initializationerror not found错误,如下: 问题分析 网上说版 ...
- MySQL 分组之后如何统计记录条数 gourp by 之后的 count()
SELECT count(*) FROM 表名 WHERE 条件 // 这样查出来的是总记录条 SELECT count(*) FROM 表名 WHERE 条件 GROUP BY id //这样统计的 ...
- 分布式锁的两种实现方式(基于redis和基于zookeeper)
先来说说什么是分布式锁,简单来说,分布式锁就是在分布式并发场景中,能够实现多节点的代码同步的一种机制.从实现角度来看,主要有两种方式:基于redis的方式和基于zookeeper的方式,下面分别简单介 ...