promise 是最先由社区提出和实现是一种解决异步编程的方案,比其余传统的解决方案(回调函数和事件)更合理和强大。编程
ES6 将其写进了语言标准,统一了用法,原生提供了 promise 对象。数组
ES6 规定,promise对象是一个构造函数,用来生成 promise 实例。promise
promise是为解决异步处理回调金字塔问题而产生的缓存
1,promise对象的状态不受外界影响异步
a,pending 初始状态异步编程
b,fulfilled 成功状态函数
c,rejected 失败状态this
promise 有以上三种状态,只有一步操做的结果能够解决当前是哪种状态,其余任何操做都没法改变这种状态;spa
2,promise 的状态一旦改变,就不会再变,任什么时候候均可以获得这个结果,状态不能够逆,只能由pending 变成fulfilled 或者pending 变成 rejectedprototype
1,没法取消promise,一旦新建它就会当即执行,没法中途取消
2,若是不设置回调函数,promise 内部抛出的错误,不会反映到外部
3,当处于 pending 状态时,没法得知目前进展到了哪个阶段,是刚刚开始仍是即将完成
1,onResolvedCallbacks 成功后要执行的回调序列 是一个数组
2,onResolvedCallbacks 失败后要执行的回调序列 是一个数组
以上两个数组存放在promise 建立实例时给promise这个类传的函数中,默认都是空数组。
每次实例 then 的时候 传入onFulfilled 成功回调 onRejected 失败回调,若是此时的状态是pending 则将onFulfilled 和 onRejected push 到对应的成功回调序列数组和失败回调序列数组中,若是此时的状态是fulfilled 则 onFulfilled 当即执行,若是此时的状态是rejected 则 onRejected 当即执行
上述序列中的回调函数执行的时候 是有顺序的,即按照顺序依次执行
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构造函数接受一个函数做为参数,该函数的两个参数分别是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); } }
咱们先来看一个例子,根据例子得出结论,而后再写源码的实现部分来验证结论
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.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。
//catch原理就是只传失败的回调 Promise.prototype.catch = function(onRejected){ this.then(null,onRejected); }
参数:接受一个数组,数组内都是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状态。
根据传入的参数不一样有不一样的功能:
值(对象、数组、字符串等):做为resolve传递出去的值
Promise实例:原封不动返回
//返回一个马上成功的promise //别人提供 给你一个方法,须要你传入一个promise,但你只有一个普通的值,你就能够经过这个方法把这个普通的值(string number object)转成一个promise对象 Promise.resolve = function(value){ return new Promise(function(resolve){ resolve(value); }); }
返回一个Promise实例,这个实例处于reject状态。
参数通常就是抛出的错误信息。
//返回一个马上失败的promise Promise.reject = function(reason){ return new Promise(function(resolve,reject){ reject(reason); }); }
参数:接受一个数组,数组内都是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); } }); }