Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
Promise三种状态
不要在解析为自身的thenable 上调用Promise.resolve。这将导致无限递归,因为它试图展平无限嵌套的promisePromise.all(iterable)
这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常被用于处理多个promise对象的状态集合。Promise.race(iterable)当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。
手写Promise
基础版
//没有解决链式调用和细节问题class MyPromise {constructor(fn) {//默认状态this.status = "pendding";//成功状态this.value = undefined;//失败状态this.reason = undefined;// 成功存放的数组this.onResolvedCallbacks = [];// 失败存放法数组this.onRejectedCallbacks = [];try {fn(this.resolve.bind(this), this.reject.bind(this));} catch (err) {console.log(err)this.reject(err);}}resolve(value) {if (this.status === "pendding") {this.value = valuethis.status = "resolve"this.onResolvedCallbacks.forEach(fn=>fn())}}reject(reason) {if (this.status === "pendding") {this.reason = reasonthis.status = "reject"this.onRejectedCallbacks.forEach(fn=>fn)}}then(onFulfilled, onRejected) {if (this.status === 'resolve') onFulfilled(this.value);if (this.status === 'reject') onRejected(this.reason)if (this.status === 'pendding') {this.onResolvedCallbacks.push(() => {onFulfilled(this.value)})if(onRejected) this.onRejectedCallbacks.push(() => onRejected(this.reason))}}}
进阶
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);};});}
