Promise 对象是用来处理异步操作的工具,解决开发者对异步回调的烦恼。
极简版
class Defer{ succeed = null fail = null state = ‘pending‘ constructor(fn) { fn(this.resolve.bind(this), this.reject.bind(this)) } resolve(result) { setTimeout(() => { this.state = ‘fulfilled‘ this.succeed(result) }) } reject(reason) { setTimeout(() => { this.state = ‘rejected‘ this.fail(reason) }) } then(succeed, fail) { this.succeed = succeed this.fail = fail } }
1.Promise 参数 executor
当新建一个promise需要用户传递一个executor函数,其形参包含Promise自行传递的resolve,reject两个方法,分别表示代理的值解析成功并传递值,代理的值解析失败并传失败原因。而如果executor在执行过程中出错,则promise立即被拒绝(调用reject)。
function Defer(executor){ if(!(this instanceof Defer)){ throw ‘Async is a constructor and should be called width "new" keyword‘; } if(typeof executor !== ‘function‘){ throw ‘Async params must be a function‘; } try{ executor.call(this, this.resolve.bind(this), this.reject.bind(this));//传递resolve,reject方法 }catch(e){//报错立即拒绝 this.reject(e); } } Async.prototype = { constructor : Async, resolve : function(value){ this.value = value;//缓存代理的值 }, reject : function(reason){ this.rejectReason = reason;//缓存失败原因 } }
2.promise状态
Defer.prototype = { constructor : Async, resolve : function(value){ this.value = value;//缓存代理的值 this.status = ‘resolved‘; }, reject : function(reason){ this.rejectReason = reason;//缓存失败原因 this.status = ‘rejected‘; } }
3.then(onFulfilled,onRejected)重要部分
then返回的是新的promise对象
//then中的onfulfilled传的参数为数值,则直接返回数值,如果为函数,则直接去调用函数。
then参数调用时期和要求
(1) onFulfilled(onResolved):可选参数,如果不是函数则必须忽略;
(2) onRejected:可选参数,如果不是函数则必须忽略;
(3) 当promise成功执行,所有onFulfilled按注册顺序执行,如果promise被拒绝,所有onRejected按注册顺序执行;
(4) onFulfilled 和 onRejected必须作为纯函数调用
(5) promise的executor执行完毕并调用resolve或reject方可调用then参数onFulfilled 和 onRejected。
(6) 无论promise状态是resolved还是rejected,只要还有未执行onFulfilled,onRejected或catch(只处理reject状态)存在且调用,返回的promise均为resolved状态;(该规则在下一节”triggerThen处理”和下下节”catch异常“会有注释,一看便知)
对于规则4,必须作为传函数调用。所以传函数调用,是不包含在Object的属性当中直接引用,并且this的值是undefined。
onFulfilled.call(undefined, promise_value);
对于规则5,等待executor执行完毕并调用resolve或reject方可调用then参数。then方法就是缓存参数。
function Defer(executor) { if (!(this instanceof Defer)) { throw ‘Defer is a constructor and should be called width "new" keyword‘; } if (typeof executor !== ‘function‘) { throw ‘Defer params must be a function‘; } this.thenCache = [];//{resolve:,reject:} this.errorHandle = null; this.status = ‘pendding‘; this.value = null; this.rejectReason = null; var self = this; setTimeout(function () { try { executor.call(self, self.resolve.bind(self), self.reject.bind(self));//传递resolve,reject方法 } catch (e) { self.reject(e); } }, 0); return this; } Defer.prototype.resolve = function (value) { this.status = ‘resolved‘; this.value = value; this.triggerThen(); }; Defer.prototype.reject = function (reason) { this.status = ‘rejected‘; this.rejectReason = reason; this.triggerThen(); }; Defer.prototype.then = function (resolve, reject) { var todo = { resolve: resolve, reject: reject }; this.thenCache.push(todo); return this; }; Defer.prototype.triggerThen = function () { var current = this.thenCache.shift(); var res = null; if (!current && this.status === ‘resolved‘) {//成功解析并读取完then cache return this; } else if (!current && this.status === ‘rejected‘) {//解析失败并读取完then cache,直接调用errorHandle if (this.errorHandle) { this.value = this.errorHandle.call(undefined, this.rejectReason); this.status = ‘resolved‘; } return this; }; if (this.status === ‘resolved‘) { res = current.resolve; } else if (this.status === ‘rejected‘) { res = current.reject; } if (typeof res === ‘function‘) { try { this.value = res.call(undefined, this.value || this.rejectReason);//重置promise的value this.status = ‘resolved‘; this.triggerThen();//继续执行then链 } catch (e) { this.status = ‘rejected‘;//异常,则promise为reject this.rejectReason = e; return this.triggerThen();//触发then链 } } else {//不是函数则忽略 this.triggerThen(); } }; Defer.prototype.catch = function (fn) { if (typeof fn === ‘function‘) { this.errorHandle = fn; } };
(方法返回一个promise实例,所有的promise都返回resolved,则resolved。如果有一个promise失败(rejected),则实例回调失败,失败原因返回第一个promise的结果)
Promise2.all = function(arrP) { let list = [] let len = 0 let hasErr = false return new Promise2((resolve, reject) => { for(let i = 0; i < arrP.length; i++) { arrP[i].then( data=> { list[i] = data len++ len === arrP.length && resolve(list) }, error => { !hasErr && reject(error) hasErr = true }) } }) }
方法返回一个promise实例,一旦迭代器中的某个 promise 完成(resolved)或失败(rejected),返回的 promise 就会 resolve 或 reject
返回第一个resolve或者reject的结果值。
Promise2.race = function(arrP) { let hasValue = false let hasError = false return new Promise2((resolve, reject) => { for(let i = 0; i < arrP.length; i++) { arrP[i].then(data => { !hasValue && !hasError && resolve(data) hasValue = true }, error => { !hasValue && !hasError &&reject(error) hasError = true }) } }) }
方法返回一个在所有给定的promise都已经fulfilled
或rejected
后的promise,并带有一个对象数组,每个对象表示对应的promise结果。
适用于:多个彼此不依赖的异步任务完成时,可以知道每个promise的结果。
Defer.allSettled = function (values) { function isPromise(x) { if ((typeof x === ‘object‘ && x != null) || typeof x === ‘function‘) { if (typeof x.then == ‘function‘) { return true; } } return false; } return new Defer((resolve, reject) => { let arr = []; let times = 0; function collectResult(val, key, obj) { arr[key] = obj; if (++times === values.length) { return resolve(arr); } } // 循环每一项拿到返回结果 values.forEach((element, index) => { if (element && isPromise(element)) { element.then(y => { let obj = { status: ‘fulfilled‘, value: y, } collectResult(y, index, obj) }, (err) => { let obj = { status: "rejected", reason: err } collectResult(err, index, obj) }) } else { let obj = { status: ‘fulfilled‘, value: value, } collectResult(value, index, obj) } }); }) }
手写promise.any()
返回第一个成功的 promise
。只要有一个 promise
成功此方法就会终止,它不会等待其他的 promise
全部完成。如果没有成功的,则将返回一个失败的promise和AggregateError
类型的实例。是一个Error的子类,将用于把单一的错误集合在一起。
Defer.any = function (values) { const num = values.length; const rejectedList = new Array(num); let rejectedNum = 0; return new Defer((resolve, reject) => { values.forEach((el, i) => { Defer.resolve(el).then( resolve(el) ).catch(err => { rejectedList[index] = err; if (++rejectedNum === num) { reject(rejectedList); } }) }) }) }
手写实现 Promise.prototype.finally()
finally()
方法返回一个Promise
。在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。这为在Promise
是否成功完成后都需要执行的代码提供了一种方式。
实例执行完then或者catch触发,
Defer.prototype.finally=function(cb){ return new Defer((resolve,reject)=>{ this.then((result)=>{ cb(); resolve(result); },(reason)=>{ cb(); reject(reason); }) }) }
代码完整:https://github.com/yaqian96/promise.git
原文:https://www.cnblogs.com/lyq1996/p/14202289.html