Promise的含义
Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件,更合理和更强大。
Promise实现过程
一实现resolve和reject输出
//4 定义常量(成功使用fulfilled 失败使用rejected 等待使用pending) let PENDING = 'pending'; let FULFILLED = 'fulfilled'; let REJECTED = 'rejected'; //1 创建一个MyPromise类 class MyPromise{ //初始化status 状态为pending status = PENDING; //6.MyPromise类中定义value和reason,用来储存执行器执行成功和失败的返回值 value= null; reason = null; //2 通过构造函数constructor,在执行这个类的时候传递一个执行器并立即执行 constructor(executor){ executor(this.resolve, this.reject) } //3 定义resolve和reject方法 //5.完成resolve和reject函数的状态改变(需要判断状态是否可以改变) resolve=(value) =>{ if(this.status !== PENDING) return; this.status = FULFILLED; console.log("resolve=>",value) //resolve=> 成功 this.value = value; } reject = (reason)=>{ if(this.status !== PENDING) return; this.status = REJECTED; console.log("reject =>",reason) //reject => 失败 this.reason = reason; } } const promise = new MyPromise((resolve,reject)=>{ resolve("成功") //reject('失败') })
二,实现简单的then方法
1实现简单的then
//7.MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值,失败回调一个参数 表示失败的原因 then(onFulfilled, onRejected){ if(this.status === FULFILLED){ onFulfilled(this.value) } if(this.status === REJECTED){ onRejected(this.reason) } } const promise = new MyPromise((resolve,reject)=>{ //resolve("成功") reject('失败') }) promise.then(value=>{ console.log("1",value) //1 成功 },reason=>{ console.log("2",reason) //2 失败 })
2处理定时器的情况,导致promise没有输出值
const promise = new MyPromise((resolve,reject)=>{ setTimeout(()=>{ resolve("成功") },2000) //reject('失败') }) promise.then(value=>{ console.log("1",value) },reason=>{ console.log("2",reason) })
//4 定义常量(成功使用fulfilled 失败使用rejected 等待使用pending) let PENDING = 'pending'; let FULFILLED = 'fulfilled'; let REJECTED = 'rejected'; //1 创建一个MyPromise类 class MyPromise{ //初始化status 状态为pending status = PENDING; //6.MyPromise类中定义value和reason,用来储存执行器执行成功和失败的返回值 value= null; reason = null; //9.实现then方法多次调用添加多个处理函数 初始化回调为数组依次执行 fulfilledCallacks = [] rejectedCallbacks = []; //2 通过构造函数constructor,在执行这个类的时候传递一个执行器并立即执行 constructor(executor){ executor(this.resolve, this.reject) } //3 定义resolve和reject方法 //5.完成resolve和reject函数的状态改变(需要判断状态是否可以改变) resolve=(value) =>{ if(this.status !== PENDING) return; this.status = FULFILLED; console.log("resolve=>",value) //成功 this.value = value; this.fulfilledCallacks.forEach((onFulfilled)=>{ onFulfilled() }) } reject = (reason)=>{ if(this.status !== PENDING) return; this.status = REJECTED; console.log("reject =>",reason) //失败 this.reason = reason; this.rejectedCallbacks.forEach((onRejected)=>{ onRejected() }) } //7.MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值,失败回调一个参数 表示失败的原因 then(onFulfilled, onRejected){ // 8.处理异步逻辑(pending状态下在then中将回调存起来) if(this.status === PENDING){ this.fulfilledCallacks.push(()=>{ onFulfilled(this.value) }) this.rejectedCallbacks.push(()=>{ onRejected(this.reason) }) } if(this.status === FULFILLED){ onFulfilled(this.value) } if(this.status === REJECTED){ onRejected(this.reason) } } } const promise = new MyPromise((resolve,reject)=>{ setTimeout(()=>{ resolve("成功") //reject('失败') },2000) }) promise.then(value=>{ console.log("1",value) },reason=>{ console.log("2",reason) })
三 then方法链式调用
1 简单的链式调用
//7.MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值,失败回调一个参数 表示失败的原因 then(onFulfilled, onRejected){ // 10. 实现then方法链式调用(写一个函数方法专门判断回调的结果是普通值还是promise,then方法返回的仍然是一个promise) let promise2 = new MyPromise((resolve,reject)=>{ // 8.处理异步逻辑(pending状态下在then中将回调存起来) if(this.status === FULFILLED){ let x = onFulfilled(this.value); resolve(x) }else if(this.status === REJECTED){ let x = onRejected(this.reason) reject(x) }else{ this.fulfilledCallacks.push(()=>{ let x = onFulfilled(this.value); resolve(x) }) this.rejectedCallbacks.push(()=>{ let x = onRejected(this.reason) reject(x) }) } }) return promise2 } const promise = new MyPromise((resolve,reject)=>{ // setTimeout(()=>{ resolve("成功") //reject('失败') // },2000) }) promise.then(value=>{ console.log("1",value) //1 成功 return 100; },reason=>{ console.log("2",reason) return 200 }).then(value=>{ console.log("then2", value) //then2 100 },reason=>{ console.log("then2", reason) })
2 promise对象子返回循环报错
//7.MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值,失败回调一个参数 表示失败的原因 then(onFulfilled, onRejected){ // 10. 实现then方法链式调用(写一个函数方法专门判断回调的结果是普通值还是promise,then方法返回的仍然是一个promise) let promise2 = new MyPromise((resolve,reject)=>{ // 8.处理异步逻辑(pending状态下在then中将回调存起来) if(this.status === FULFILLED){ //判断x是普通函数还是promise函数 //如果普通函数直接调用resolve //如果是promise对象,查看promise的返回结果,在根据结果调用对应的方法 //* 为了解决获取promise2,所以加一个定时器 setTimeout(()=>{ let x = onFulfilled(this.value); resolvePromise(promise2, x,resolve,reject) }) }else if(this.status === REJECTED){ let x = onRejected(this.reason) reject(x) }else{ this.fulfilledCallacks.push(()=>{ let x = onFulfilled(this.value); resolve(x) }) this.rejectedCallbacks.push(()=>{ let x = onRejected(this.reason) reject(x) }) } }) return promise2 } //11 处理promise返回值各种类型情况(普通值,promise) function resolvePromise(promise2, x, resolve, reject){ if(promise2 == x){ return reject(new TypeError('Chaining cycle detected for promise #<Promise>')) } if(x instanceof MyPromise){ //promise对象 x.then(resolve, reject); }else{ //普通值 resolve(x) } } //promise对象子返回循环报错 let promise = new MyPromise((resolve,reject)=>{ // setTimeout(()=>{ resolve("成功") //reject('失败') // },2000) }) let p1 = promise.then(value=>{ console.log(value); // return p1; }) p1.then(value=>{ console.log(value) },reason=>{ console.log(reason.message) //Chaining cycle detected for promise #<Promise> })
then进一步封装
//4 定义常量(成功使用fulfilled 失败使用rejected 等待使用pending) let PENDING = 'pending'; let FULFILLED = 'fulfilled'; let REJECTED = 'rejected'; //1 创建一个MyPromise类 class MyPromise{ //初始化status 状态为pending status = PENDING; //6.MyPromise类中定义value和reason,用来储存执行器执行成功和失败的返回值 value= null; reason = null; //9.实现then方法多次调用添加多个处理函数 初始化回调为数组依次执行 fulfilledCallacks = [] rejectedCallbacks = []; //2 通过构造函数constructor,在执行这个类的时候传递一个执行器并立即执行 constructor(executor){ try{ executor(this.resolve, this.reject) }catch(e){ this.reject(e); } } //3 定义resolve和reject方法 //5.完成resolve和reject函数的状态改变(需要判断状态是否可以改变) resolve=(value) =>{ if(this.status !== PENDING) return; this.status = FULFILLED; console.log("resolve=>",value) //成功 this.value = value; // 执行成功回调 while(this.fulfilledCallacks.length){ this.fulfilledCallacks.shift()() } } reject = (reason)=>{ if(this.status !== PENDING) return; this.status = REJECTED; this.reason = reason; // 执行成功回调 while(this.rejectedCallbacks.length){ this.rejectedCallbacks.shift()() } } //7.MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值,失败回调一个参数 表示失败的原因 then(onFulfilled, onRejected){ // 10. 实现then方法链式调用(写一个函数方法专门判断回调的结果是普通值还是promise,then方法返回的仍然是一个promise) let promise2 = new MyPromise((resolve,reject)=>{ // 8.处理异步逻辑(pending状态下在then中将回调存起来) if(this.status === FULFILLED){ //判断x是普通函数还是promise函数 //如果普通函数直接调用resolve //如果是promise对象,查看promise的返回结果,在根据结果调用对应的方法 //* 为了解决获取promise2,所以加一个定时器 setTimeout(()=>{ try{ let x = onFulfilled(this.value); resolvePromise(promise2, x,resolve,reject) }catch(e){ reject(e); } }) }else if(this.status === REJECTED){ setTimeout(()=>{ try{ let x = onRejected(this.reason); resolvePromise(promise2, x,resolve,reject); }catch(e){ reject(e); } }) }else{ this.fulfilledCallacks.push(()=>{ setTimeout(()=>{ try{ let x = onFulfilled(this.value); resolvePromise(promise2, x,resolve,reject) }catch(e){ reject(e); } }) }) this.rejectedCallbacks.push(()=>{ setTimeout(()=>{ try{ let x = onRejected(this.reason); resolvePromise(promise2, x,resolve,reject); }catch(e){ reject(e); } }) }) } }) return promise2 } } //11 处理promise返回值各种类型情况(普通值,promise) function resolvePromise(promise2, x, resolve, reject){ if(promise2 == x){ return reject(new TypeError('Chaining cycle detected for promise #<Promise>')) } if(x instanceof MyPromise){ //promise对象 x.then(resolve, reject); }else{ //普通值 resolve(x) } } var promise = new MyPromise(function(resolve, reject) { setTimeout(() => { resolve('成功') },2000) // resolve('成功') }) promise.then(value => { console.log(value) // throw new Error('then error') return 'aaa' }, reason => { console.log(reason) return 1000 }).then(value => { console.log('value2') console.log(value) }, reason => { console.log('报错2') console.log(reason) })
then参数可变的情况
then(onFulfilled, onRejected){ onFulfilled= onFulfilled? onFulfilled: value =>this.value; onRejected= onRejected? onRejected: reason =>{throw this.reason}; }
//处理没有参数的情况
.then().then()
四Promise.all
static all(array){ let result=[]; let index=0; return new MyPromise((resolve,reject)=>{ function addData(key,value){ result[key]=value; index++; if(index==array.length){ resolve(result) } } for(let i=0;i<array.length;i++){ let current = array[i]; if(current instanceof MyPromise){ //promise对象 current.then(value=>addData(i,value),reason=>reject(i,reason)) }else{ //普通值 addData(i,array[i]) } } }) } function p1() { return new Promise(function (resolve, reject) { setTimeout(function() { resolve('p1') },2000) }) } function p2() { return new Promise(function (resolve, reject) { resolve('p2') }) } MyPromise.all(['a', 'b', p1(), p2(), 'c']).then(function(result) { // result -> ['a', 'b', 'p1', 'p2', 'c'] console.log(result) })
五Promise.resolve
//Promise.resolve static resolve(value){ //参数为promise对象直接输出 if(value instanceof MyPromise) return value; //参数为普通值,就创建promise方法 return new MyPromise(resolve=>resolve(value)) } function p1() { return new MyPromise(function (resolve, reject) { resolve('hello') }) } MyPromise.resolve(10).then(value => console.log(value)) MyPromise.resolve(p1()).then(value => console.log(value))
Promise.reject
//Promise.reject 返回rejected状态的promise static reject(value){ return new MyPromise((undefined,reject)=>{ reject(value) }) }
六Promise.finally
//Promise.finally finally(callback){ //通过then获取当前promise对象的状态 return this.then(value=>{ return MyPromise.resolve(callback()).then(()=>value); },reason=>{ return MyPromise.resolve(callback()).then(()=>{throw reason}); }) }
七 Promise.catch
//Promise.prototype.catch catch(failCallback){ return this.then(undefined,failCallback) }
整体代码
/** * 手写Promise * 1.创建MyPromise类 * 2.通过构造函数constructor,在执行这个类的时候需要传递一个执行器进去并立即调用 * 3.定义resolve和reject * 4.定义状态常量(成功fulfilled失败rejected等待pending),初始化为pending * 5.完成resolve和reject函数的状态改变(需要判断状态是否可以改变) * 6.MyPromise类中定义value和reason,用来储存执行器执行成功和失败的返回值 * 7.MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值,失败回调一个参数 表示失败的原因 * 8.处理异步逻辑(pending状态下在then中将回调存起来) * 9.实现then方法多次调用添加多个处理函数 初始化回调为数组依次执行 * 10.实现then方法链式调用(写一个函数方法专门判断回调的结果是普通值还是promise,then方法返回的仍然是一个promise * 11处理promise返回值各种类型情况 * 12then方法链式调用识别Promise对象返回 * 13promise实现捕获错误及then链式调用其他状态代码补充 * 14将then方法的参数变为可选参数 * 15 Promise.all * 16 Promise.resolve返回promise * 17 finally方法 不管成功失败都会执行一次 * 18 catch方法实现 * 19 reject方法实现 * 20 race方法实现 */ //4 定义常量(成功使用fulfilled 失败使用rejected 等待使用pending) let PENDING = 'pending'; let FULFILLED = 'fulfilled'; let REJECTED = 'rejected'; //1 创建一个MyPromise类 class MyPromise{ //初始化status 状态为pending status = PENDING; //6.MyPromise类中定义value和reason,用来储存执行器执行成功和失败的返回值 value= null; reason = null; //9.实现then方法多次调用添加多个处理函数 初始化回调为数组依次执行 fulfilledCallacks = [] rejectedCallbacks = []; //2 通过构造函数constructor,在执行这个类的时候传递一个执行器并立即执行 constructor(executor){ try{ executor(this.resolve, this.reject) }catch(e){ this.reject(e); } } //3 定义resolve和reject方法 //5.完成resolve和reject函数的状态改变(需要判断状态是否可以改变) resolve=(value) =>{ if(this.status !== PENDING) return; this.status = FULFILLED; console.log("resolve=>",value) //成功 this.value = value; // 执行成功回调 while(this.fulfilledCallacks.length){ this.fulfilledCallacks.shift()() } } reject = (reason)=>{ if(this.status !== PENDING) return; this.status = REJECTED; this.reason = reason; // 执行成功回调 while(this.rejectedCallbacks.length){ this.rejectedCallbacks.shift()() } } //7.MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值,失败回调一个参数 表示失败的原因 then(onFulfilled, onRejected){ onFulfilled= onFulfilled? onFulfilled: value =>this.value; onRejected= onRejected? onRejected: reason =>{throw this.reason}; // 10. 实现then方法链式调用(写一个函数方法专门判断回调的结果是普通值还是promise,then方法返回的仍然是一个promise) let promise2 = new MyPromise((resolve,reject)=>{ // 8.处理异步逻辑(pending状态下在then中将回调存起来) if(this.status === FULFILLED){ //判断x是普通函数还是promise函数 //如果普通函数直接调用resolve //如果是promise对象,查看promise的返回结果,在根据结果调用对应的方法 //* 为了解决获取promise2,所以加一个定时器 setTimeout(()=>{ try{ let x = onFulfilled(this.value); resolvePromise(promise2, x,resolve,reject) }catch(e){ reject(e); } }) }else if(this.status === REJECTED){ setTimeout(()=>{ try{ let x = onRejected(this.reason); resolvePromise(promise2, x,resolve,reject); }catch(e){ reject(e); } }) }else{ this.fulfilledCallacks.push(()=>{ setTimeout(()=>{ try{ let x = onFulfilled(this.value); resolvePromise(promise2, x,resolve,reject) }catch(e){ reject(e); } }) }) this.rejectedCallbacks.push(()=>{ setTimeout(()=>{ try{ let x = onRejected(this.reason); resolvePromise(promise2, x,resolve,reject); }catch(e){ reject(e); } }) }) } }) return promise2 } //Promise.prototype.finally finally(callback){ //通过then获取当前promise对象的状态 return this.then(value=>{ return MyPromise.resolve(callback()).then(()=>value); },reason=>{ return MyPromise.resolve(callback()).then(()=>{throw reason}); }) } //Promise.prototype.catch catch(failCallback){ return this.then(undefined,failCallback) } //Promise.all static all(array){ let result=[]; let index=0; return new MyPromise((resolve,reject)=>{ function addData(key,value){ result[key] = value; index++; if(index===array.length){ resolve(result); } } for(let i=0;i<array.length;i++){ let current = array[i]; if(current instanceof MyPromise){ //promise对象 current.then(value=>addData(i,value),reason=>addData(i,reason)) }else{ //普通值 addData(i,array[i]) } } }) } //Promise.race static race(promises){ return new MyPromise((resolve,reject)=>{ //判断是不是数组 if(!Array.isArray(promises)){ return reject(new TypeError('Argument is not iterable')); } //等待第一个被敲定 promises.forEach(p=>{ MyPromise.resolve(p).then(res=>{resolve(res)},err=>{reject(err)}) }) }) } //Promise.resolve static resolve(value){ //参数为promise对象直接输出 if(value instanceof MyPromise) return value; //参数为普通值,就创建promise方法 return new MyPromise(resolve=>resolve(value)) } //Promise.reject 返回rejected状态的promise static reject(value){ return new MyPromise((undefined,reject)=>{ reject(value) }) } } //11 处理promise返回值各种类型情况(普通值,promise) function resolvePromise(promise2, x, resolve, reject){ if(promise2 == x){ return reject(new TypeError('Chaining cycle detected for promise #<Promise>')) } if(x instanceof MyPromise){ //promise对象 x.then(resolve, reject); }else{ //普通值 resolve(x) } } const p1 = new MyPromise((resolve,reject)=>{ setTimeout(()=>{ resolve(1) },2000) }) const p2 = new MyPromise((resolve,reject)=>{ setTimeout(()=>{ reject(2) },1000) }) MyPromise.race([p1,p2]).then(res=>{ console.log("res",res); },err=>{ console.log('err',err) })
日常所遇,随手而记。