咱们工做中免不了运用promise用来解决异步回调问题。平时用的不少库或者插件都运用了promise 例如axios、fetch等等。可是你知道promise是咋写出来的呢?ios
别怕~这里有本promisesA+规范,便宜点10元卖给你了。npm
首先呢,promise确定是一个类,咱们就用class来声明。axios
new Promise((resolve, reject)=>{})
,因此传入一个参数(函数),秘籍里叫他executor,传入就执行。class Promise{ // 构造器 constructor(executor){ // 成功 let resolve = () => { }; // 失败 let reject = () => { }; // 当即执行 executor(resolve, reject); } }
Promise存在三个状态(state)pending、fulfilled、rejected数组
pending(等待态)为初始态,并能够转化为fulfilled(成功态)和rejected(失败态)promise
成功时,不可转为其余状态,且必须有一个不可改变的值(value)异步
失败时,不可转为其余状态,且必须有一个不可改变的缘由(reason)函数
new Promise((resolve, reject)=>{resolve(value)})
resolve为成功,接收参数value,状态改变为fulfilled,不可再次改变。post
new Promise((resolve, reject)=>{reject(reason)})
reject为失败,接收参数reason,状态改变为rejected,不可再次改变。测试
如果executor函数报错 直接执行reject();fetch
因而乎,咱们得到如下代码
class Promise{ constructor(executor){ // 初始化state为等待态 this.state = 'pending'; // 成功的值 this.value = undefined; // 失败的缘由 this.reason = undefined; let resolve = value => { // state改变,resolve调用就会失败 if (this.state === 'pending') { // resolve调用后,state转化为成功态 this.state = 'fulfilled'; // 储存成功的值 this.value = value; } }; let reject = reason => { // state改变,reject调用就会失败 if (this.state === 'pending') { // reject调用后,state转化为失败态 this.state = 'rejected'; // 储存失败的缘由 this.reason = reason; } }; // 若是executor执行报错,直接执行reject try{ executor(resolve, reject); } catch (err) { reject(err); } } }
class Promise{ constructor(executor){...} // then 方法 有两个参数onFulfilled onRejected then(onFulfilled,onRejected) { // 状态为fulfilled,执行onFulfilled,传入成功的值 if (this.state === 'fulfilled') { onFulfilled(this.value); }; // 状态为rejected,执行onRejected,传入失败的缘由 if (this.state === 'rejected') { onRejected(this.reason); }; } }
这下武学初成,能够对付对付江湖小杂毛了,可是对于带setTimeout的江洋大盗仍是没辙。
如今基本能够实现简单的同步代码,可是当resolve在setTomeout内执行,then时state仍是pending等待状态 咱们就须要在then调用的时候,将成功和失败存到各自的数组,一旦reject或者resolve,就调用它们
相似于发布订阅,先将then里面的两个函数储存起来,因为一个promise能够有多个then,因此存在同一个数组内。
// 多个then的状况 let p = new Promise(); p.then(); p.then();
成功或者失败时,forEach调用它们
class Promise{ constructor(executor){ this.state = 'pending'; this.value = undefined; this.reason = undefined; // 成功存放的数组 this.onResolvedCallbacks = []; // 失败存放法数组 this.onRejectedCallbacks = []; let resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; // 一旦resolve执行,调用成功数组的函数 this.onResolvedCallbacks.forEach(fn=>fn()); } }; let reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; // 一旦reject执行,调用失败数组的函数 this.onRejectedCallbacks.forEach(fn=>fn()); } }; try{ executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled,onRejected) { if (this.state === 'fulfilled') { onFulfilled(this.value); }; if (this.state === 'rejected') { onRejected(this.reason); }; // 当状态state为pending时 if (this.state === 'pending') { // onFulfilled传入到成功数组 this.onResolvedCallbacks.push(()=>{ onFulfilled(this.value); }) // onRejected传入到失败数组 this.onRejectedCallbacks.push(()=>{ onRejected(this.value); }) } } }
我门经常用到new Promise().then().then()
,这就是链式调用,用来解决回调地狱
一、为了达成链式,咱们默认在第一个then里返回一个promise。秘籍规定了一种方法,就是在then里面返回一个新的promise,称为promise2:promise2 = new Promise((resolve, reject)=>{})
二、当咱们在第一个then中return
了一个参数(参数未知,需判断)。这个return出来的新的promise就是onFulfilled()或onRejected()的值
秘籍则规定onFulfilled()或onRejected()的值,即第一个then返回的值,叫作x,判断x的函数叫作resolvePromise
return
的对象)、resolve、rejectclass Promise{ constructor(executor){ this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onResolvedCallbacks = []; this.onRejectedCallbacks = []; let resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onResolvedCallbacks.forEach(fn=>fn()); } }; let reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(fn=>fn()); } }; try{ executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled,onRejected) { // 声明返回的promise2 let promise2 = new Promise((resolve, reject)=>{ if (this.state === 'fulfilled') { let x = onFulfilled(this.value); // resolvePromise函数,处理本身return的promise和默认的promise2的关系 resolvePromise(promise2, x, resolve, reject); }; if (this.state === 'rejected') { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); }; if (this.state === 'pending') { this.onResolvedCallbacks.push(()=>{ let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); }) this.onRejectedCallbacks.push(()=>{ let x = onRejected(this.value); resolvePromise(promise2, x, resolve, reject); }) } }); // 返回promise,完成链式 return promise2; } }
秘籍规定了一段代码,让不一样的promise代码互相套用,叫作resolvePromise
let p = new Promise(resolve => { resolve(0); }); var p2 = p.then(data => { // 循环引用,本身等待本身完成,一生完不成 return p2; })
一、判断x
let then = x.then
二、当x是对象或者函数(默认promise)function resolvePromise(promise2, x, resolve, reject){ // 循环引用报错 if(x === promise2){ // reject报错 return reject(new TypeError('Chaining cycle detected for promise')); } // 防止屡次调用 let called; // x不是null 且x是对象或者函数 if (x != null && (typeof x === 'object' || typeof x === 'function')) { try { // A+规定,声明then = x的then方法 let then = x.then; // 若是then是函数,就默认是promise了 if (typeof then === 'function') { // 就让then执行 第一个参数是this 后面是成功的回调 和 失败的回调 then.call(x, y => { // 成功和失败只能调用一个 if (called) return; called = true; // resolve的结果依旧是promise 那就继续解析 resolvePromise(promise2, y, resolve, reject); }, err => { // 成功和失败只能调用一个 if (called) return; called = true; reject(err);// 失败了就失败了 }) } else { resolve(x); // 直接成功便可 } } catch (e) { // 也属于失败 if (called) return; called = true; // 取then出错了那就不要在继续执行了 reject(e); } } else { resolve(x); } }
一、秘籍规定onFulfilled,onRejected都是可选参数,若是他们不是函数,必须被忽略
value => value
reason => throw err
二、秘籍规定onFulfilled或onRejected不能同步被调用,必须异步调用。咱们就用setTimeout解决异步问题class Promise{ constructor(executor){ this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onResolvedCallbacks = []; this.onRejectedCallbacks = []; let resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onResolvedCallbacks.forEach(fn=>fn()); } }; let reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(fn=>fn()); } }; try{ executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled,onRejected) { // onFulfilled若是不是函数,就忽略onFulfilled,直接返回value onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; // onRejected若是不是函数,就忽略onRejected,直接扔出错误 onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }; let promise2 = new Promise((resolve, reject) => { if (this.state === 'fulfilled') { // 异步 setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }; if (this.state === 'rejected') { // 异步 setTimeout(() => { // 若是报错 try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }; if (this.state === 'pending') { this.onResolvedCallbacks.push(() => { // 异步 setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }); this.onRejectedCallbacks.push(() => { // 异步 setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0) }); }; }); // 返回promise,完成链式 return promise2; } }
顺便附赠catch和resolve、reject、race、all方法
class Promise{ constructor(executor){ this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onResolvedCallbacks = []; this.onRejectedCallbacks = []; let resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onResolvedCallbacks.forEach(fn=>fn()); } }; let reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(fn=>fn()); } }; try{ executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled,onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }; let promise2 = new Promise((resolve, reject) => { if (this.state === 'fulfilled') { setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }; if (this.state === 'rejected') { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }; if (this.state === 'pending') { this.onResolvedCallbacks.push(() => { setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0) }); }; }); return promise2; } catch(fn){ return this.then(null,fn); } } function resolvePromise(promise2, x, resolve, reject){ if(x === promise2){ return reject(new TypeError('Chaining cycle detected for promise')); } let called; if (x != null && (typeof x === 'object' || typeof x === 'function')) { try { let then = x.then; if (typeof then === 'function') { then.call(x, y => { if(called)return; called = true; resolvePromise(promise2, y, resolve, reject); }, err => { if(called)return; called = true; reject(err); }) } else { resolve(x); } } catch (e) { if(called)return; called = true; reject(e); } } else { resolve(x); } } //resolve方法 Promise.resolve = function(val){ return new Promise((resolve,reject)=>{ resolve(val) }); } //reject方法 Promise.reject = function(val){ return new Promise((resolve,reject)=>{ reject(val) }); } //race方法 Promise.race = function(promises){ return new Promise((resolve,reject)=>{ for(let i=0;i<promises.length;i++){ promises[i].then(resolve,reject) }; }) } //all方法(获取全部的promise,都执行then,把结果放到数组,一块儿返回) Promise.all = function(promises){ let arr = []; let i = 0; function processData(index,data){ arr[index] = data; i++; if(i == promises.length){ resolve(arr); }; }; return new Promise((resolve,reject)=>{ for(let i=0;i<promises.length;i++){ promises[i].then(data=>{ processData(i,data); },reject); }; }); }
一、先在后面加上下述代码
二、npm 有一个promises-aplus-tests插件 npm i promises-aplus-tests -g 能够全局安装 mac用户最前面加上sudo
三、命令行 promises-aplus-tests [js文件名] 便可验证
// 目前是经过他测试 他会测试一个对象 // 语法糖 Promise.defer = Promise.deferred = function () { let dfd = {} dfd.promise = new Promise((resolve,reject)=>{ dfd.resolve = resolve; dfd.reject = reject; }); return dfd; } module.exports = Promise; //npm install promises-aplus-tests 用来测试本身的promise 符不符合promisesA+规范
做者:卡姆爱卡姆 连接:https://juejin.im/post/5b2f02cd5188252b937548ab 来源:掘金 著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。