Promise详解
1. Promise基本使用:
【1】Promise:两个实例参数,分别为PromiseState和PromiseResult,前者表示Promise状态,后者表示改变状态时传入的data数据.
const p = new Promise((resolve, reject) => { resolve('Hello Promise Resolve'); });
此时p为一个Promise对象,其PromiseState为fulfilled,PromiseResult为字符串'Hello Promise Resolve'
PromiseState三种状态: (1) pending 等待被改变状态 (2)fulfilled 成功(3)rejected 失败
【2】Promise.reject(data) :返回一个PromiseState为rejected的Promise对象,其PromiseResult根据data决定
【3】Promise.resolve(data) :返回一个Promise对象,其PromiseResult根据data决定
其PromiseState分情况讨论:
1. 若data为非Promise对象,则状态为fulfilled
2. 若data为Promise对象,且其调用resolve,即data结果状态为fulfilled,那么此时返回的Promise对象状态也为fulfilled
3. 若data为Promise对象,且其调用reject或throw抛出异常,即data结果状态为rejected,那么此时返回的Promise对象状态也为rejected
【4】Promise.prototype.then(onResolved,onRejected) :若Promise的状态为fulfilled,执行onResolved函数,否则执行onRejected函数,均返回一个Promise对象,且返回对象的状态和
Promise.resolve(data)方法判定方式一样. 【!!!即使是then方法的第二个函数也是如此,第二个函数不是无论如何都返回rejected】
【5】Promise.prototype.catch()
【6】Promise.all(Promises: Array) :数组中所有Promise对象的状态为成功才返回一个成功的Promise对象,否则返回一个失败的Promise对象.
成功时,PromiseResult包含所有数组中对象的data,而失败时只包含失败的Promise对象结果.
【7】Promise.race(Promises: Array) :数组中第一个改变状态的Promise对象的即返回的Promise对象.
2. Promise需要注意的问题:
【1】当指定多个成功或失败回调函数,即一个Promise对象执行多次then,它们均会执行.
【2】Promise对象改变状态和执行回调函数执行顺序问题:
情况一:先改变状态
(1)执行器中直接同步执行resolve、reject或抛出异常
const p = new Promise((resolve, reject) => {
// 此处代码同步执行 resolve(); }); p.then(res => { console.log(res) }, err => { console.log(err) });
(2)执行器中异步执行resolve、reject,但then方法同样异步执行,且执行时间比前者晚
const p = new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, 1000) }); setTimeout(() => { p.then(res => { console.log(res) }, err => { console.log(err) }); }, 2000);
【3】异常穿透
【4】链式调用
【5】中断链式调用 :在then中手动返回一个状态为pending的Promise对象即可
3. Promise手写源码:
【1】Promise对象
function Promise(executor) { this.PromiseState = 'pending'; this.PromiseResult = undefined; const self = this; /* 当进行异步执行resolve和reject时,先执行回调,再改变状态, 那么需要在执行回调时先把onResolved和onRejected保存,等改变状态时再执行 */ this.callbacks = []; function resolve(data) { /* 判断确保Promise对象状态只能改变一次,即同时出现resolve和reject,只执行一次 */ if (self.PromiseState !== 'pending') return; self.PromiseResult = data; self.PromiseState = 'fulfilled'; // 多个then回调函数都可以执行 setTimeout(() => { self.callbacks.forEach(item => { item.onResolved(data); }) }); } function reject(data) { if (self.PromiseState !== 'pending') return; self.PromiseResult = data; self.PromiseState = 'rejected'; setTimeout(() => { self.callbacks.forEach(item => { item.onRejected(data); }) }); } try { executor(resolve, reject); } catch (e) { reject(e); } }
【2】Promise 原型方法
(1)then
Promise.prototype.then = function (onResolved, onRejected) { const self = this; if (typeof onRejected !== 'function') { /* 用户只传入第一个函数, 解决异常穿透 */ onRejected = err => { throw err; } } if (typeof onResolved !== 'function') { onResolved = result => { return result; } } return new Promise((resolve, reject) => { function callback(type) { try { let result = type(self.PromiseResult); if (result instanceof Promise) { /* 此种判断无法获取数据,因此使用then将v和r顺利传入 */ // if (result.PromiseState === 'fulfilled') { // resolve(); // } else if (result.PromiseState === 'rejected') { // reject(); // } result.then(v => { resolve(v); }, r => { reject(r); }) } else { resolve(result); } } catch (e) { reject(e); } } if (self.PromiseState === 'pending') { this.callbacks.push({ onResolved: function () { callback(onResolved); }, onRejected: function () { callback(onRejected); } }) } else if (self.PromiseState === 'fulfilled') { setTimeout(() => { callback(onResolved); }); } else if (self.PromiseState === 'rejected') { setTimeout(() => { callback(onRejected); }); } }); };
(2)catch
Promise.prototype.catch = function (onRejected) { return this.then(undefined, onRejected); };
(3)Promise.resolve and Promise.reject
Promise.resolve = function (res) { return new Promise((resolve, reject) => { if (res instanceof Promise) { res.then(v => { resolve(v); }, r => { reject(r); }) } else { resolve(res); } }) }; Promise.reject = function (err) { return new Promise((resolve, reject) => { reject(err); }) };
(4)Promise.all
Promise.all = function (promises) { return new Promise((resolve, reject) => { let arr = []; let count = 0; for (let i=0;i<promises.length;i++) { promises[i].then(res => { arr[i] = res; /* 如果是异步,则采用arr.push会改变结果顺序,因此采用下标索引填充 */ count++; if (count === promises.length) { resolve(arr); } }, err => { reject(err); }) } }) };
(5)Promise.race
Promise.race = function (promises) { return new Promise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { promises[i].then(res => { resolve(res); }, err => { reject(err); }) } }) };

浙公网安备 33010602011771号