Promise
相关的一些实现,本身最近也在看ES6
的一些内容,因而打算本身也整理一下,提高一下理解;Promise
的人,若是你没有了解或使用过Promise
,建议先看一下 阮一峰 ECMAScript6 入门 之Promise。Promise
Promise
是一个容器,里面保存着某个将来才会结束的事件(一般是一个异步操做)的结果;Promise
对象表明一个异步操做,有三种状态:pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。Promise
对象的状态改变,只有两种可能:从pending
变为fulfilled
和从pending
变为rejected
。Promise
Promise
// Promise构造函数接收一个executor函数,executor函数执行完同步或异步操做后,调用它的两个参数resolve和reject
const promise = new Promise(function(resolve, reject) {
/*
若是操做成功,调用resolve并传入value
若是操做失败,调用reject并传入reason
*/
})
复制代码
fulfilled
的回调函数数组rejected
的回调函数数组const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
const NewPromise = function(executor) {
const _this = this;
_this.status = PENDING; // 状态
_this.data = undefined; // 值
_this.onResolvedCallback = []; // fulfilled的回调函数数组
_this.onRejectedCallback = []; // rejected的回调函数数组
// 成功
function resolve(value) { ... }
// 失败
function reject(reason) { ... }
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
复制代码
resole
和reject
resole
是成功的调用,须要不状态修改成fulfilled
,而后当前的值设为传入的值,遍历执行onResolvedCallback
中的回调。// 成功
function resolve(value) {
只有pending状态才能转换为fulfilled / rejected
setTimeout(function() { // 异步执行全部的回调函数
if (_this.status === PENDING) {
_this.status = FULFILLED;
_this.data = value;
_this.onResolvedCallback.forEach(callback => callback(value));
}
});
}
复制代码
reject
的实现和resolve
相似,只是状态修改成rejected
及执行onRejectedCallback
。// 失败
function reject(reason) {
setTimeout(function() { // 异步执行全部的回调函数
if (_this.status === PENDING) {
_this.status = REJECTED;
_this.data = reason;
_this.onRejectedCallback.forEach(callback => callback(reason));
}
});
}
复制代码
Promise
,你能够像使用Promise
同样使用它,但尚未添加其余的方法。// 测试
const promise = new NewPromise(function(resolve, reject) {
console.log('ss', 11)
})
复制代码
then
方法Promise
对象有一个then
方法,用来注册在这个Promise
状态肯定后的回调,then
方法须要写在原型链上(为何要写在原型上不清楚的可能须要补一下JavaScript
基础了)。在Promise/A
标准中,明确规定了then
要返回一个新的对象,因此在咱们的实现中也返回一个新对象。// then挂载到原型上
NewPromise.prototype.then = function(onResolved, onRejected) {
const _this = this;
if ( typeof onResolved !== 'function') {
onResolved = function(value) { return value }
}
if ( typeof onRejected !== 'function') {
onRejected = function(reason) { throw reason }
}
// 公共判断
const common = function (data, resolve, reject) {
// 考虑到有可能throw,咱们将其包在try/catch块里
try {
let value = _this.status === FULFILLED
? onResolved(data)
: onRejected(data)
if( value instanceof Promise) {
value.then(resolve, reject)
}
resolve(value)
} catch (error) {
reject(error)
}
}
// 公共判断
const pendingCommon = function (data, flag, resolve, reject) {
// 考虑到有可能throw,咱们将其包在try/catch块里
try {
let value = flag === FULFILLED
? onResolved(data)
: onRejected(data)
if( value instanceof Promise) {
value.then(resolve, reject)
}
resolve(value)
} catch (error) {
reject(error)
}
}
if (_this.status === PENDING) {
return new NewPromise(function(resolve, reject) {
_this.onResolvedCallback.push((value) => {
pendingCommon(value, FULFILLED, resolve, reject);
})
_this.onRejectedCallback.push((reason) => {
pendingCommon(reason, REJECTED, resolve, reject);
})
})
} else { // resolve / reject
return new NewPromise(function (resolve, reject) {
setTimeout(function () {
common(_this.data, resolve, reject)
})
})
}
}
复制代码
resolve
方法再次完善rosolve
的值是不是Promise
,若是是Promise
继续执行.then
方法。// 成功
function resolve(value) {
// value 若是是Promise继续执行.then
+ if (value instanceof Promise) {
+ return value.then(resolve, reject)
+ }
...
}
复制代码
catch
方法Promise
的异常错误。// catch方法
NewPromise.prototype.catch = function(onRejected) {
return this.then(null, onRejected)
}
复制代码
finally
方法finally()
方法用于指定无论Promise
对象最后状态如何,都会执行的操做。// finally
NewPromise.prototype.finally = function (fun) {
return this.then((value) => {
// f(); return value;
// Promise.resolve会等f()的函数执行完再返回结果
return NewPromise.resolve(fun()).then(() => value);
}, (err) => {
return NewPromise.resolve(fun()).then(() => {
throw err;
});
});
};
复制代码
resolve
方法Promise
对象,实例的状态为fulfilled
。NewPromise.resolve = function(value) {
if (value instanceof Promise) return value;
if (value === null) return null;
// 判断若是是promise
if (typeof value === 'object' || typeof value === 'function') {
try {
// 判断是否有then方法
let then = value.then;
if (typeof then === 'function') {
return new NewPromise(then.call(value)); // 执行value方法
}
} catch (e) {
return new NewPromise( (resolve, reject) =>{
reject(e);
});
}
}
return new NewPromise( (resolve, reject) =>{
resolve(value);
});
}
复制代码
reject
方法Promise
对象,实例的状态为rejected
。实现和resolve
方法相似,最后return改成reject
。NewPromise.reject = function(reason) {
...
return new NewPromise( (resolve, reject) =>{
reject(reason);
});
}
复制代码
all
方法Promise.all
方法用于将多个 Promise 实例,包装成一个新的Promise
实例;方法的参数能够不是数组,但必须具备Iterator
接口,且返回的每一个成员都是Promise
实例。// all
NewPromise.all = function(promises) {
return new NewPromise(function(resolve, reject) {
const result = []
// 判断参数属否是数组
promises = Array.isArray(promises) ? promises : []
const len = promises.length - 1;
promises.forEach((promise, index) => {
promise.then(value => {
result.push(value)
if(index === len) {
resolve(result)
}
}, reject)
})
})
}
复制代码
race
方法Promise.race()
方法一样是将多个Promise
实例,包装成一个新的Promise
实例。Promise.race()
的状态就跟着改变。那个率先改变的Promise
实例的返回值,就传递给Promise.race()
的回调函数。// race
NewPromise.race = function (promises) {
return new NewPromise((resolve, reject) => {
promises = Array.isArray(promises) ? promises : []
promises.forEach(promise => {
promise.then(resolve, reject)
})
})
}
复制代码
deferred
方法// defered
NewPromise.deferred = function() {
const dfd = {}
dfd.promise = new NewPromise(function(resolve, reject) {
dfd.resolve = resolve
dfd.reject = reject
})
return dfd
}
复制代码
allSettled
方法Promise.allSettled()
方法接受一组Promise
实例做为参数,包装成一个新的Promise
实例,只有等到全部这些参数实例都返回结果,无论是fulfilled仍是rejected,包装实例才会结束。返回一个包含全部结果的数组。NewPromise.allSettled = function (promises) {
return new NewPromise((resolve, reject) => {
promises = Array.isArray(promises) ? promises : []
let len = promises.length;
const argslen = len;
if (len === 0) return resolve([]);
let args = Array.prototype.slice.call(promises);
function resolvePromise(index, value) {
if(typeof value === 'object') { // 传入的是不是object
const then = value.then;
if(typeof then === 'function'){
then.call(value, function(val) {
args[index] = { status: 'fulfilled', value: val};
if(--len === 0) {
resolve(args);
}
}, function(e) {
args[index] = { status: 'rejected', reason: e };
if(--len === 0) {
reject(args);
}
})
}
}
}
for(let i = 0; i < argslen; i++){
resolvePromise(i, args[i]);
}
})
}
复制代码
// 测试
const promise = new NewPromise(function(resolve, reject) {
console.log('ss', 11);
resolve(123);
})
复制代码
then
测试promise.then(val => {
console.log('val', val)
})
复制代码
catch
测试const promise = new NewPromise(function(resolve, reject) {
console.log('ss', 11);
reject('errr')
})
promise.catch(err => {
console.log('err', err)
})
复制代码
finally
测试const resolved = NewPromise.resolve(1);
const rejected = NewPromise.reject(-1);
const resolved1 = NewPromise.resolve(17);
const p = NewPromise.all([resolved, resolved1, rejected]);
p.then((result) => {
console.log('result', result)
}).catch(err => {
console.log('err', err)
}).finally(() => {
console.log('finally')
})
复制代码
resolve
测试const resolved = NewPromise.resolve(1);
resolved.then(val => {
console.log('resolved', val)
})
复制代码
reject
测试const rejected = NewPromise.reject(-1);
rejected.catch(val => {
console.log('rejected', val)
})
复制代码
all
测试const resolved = NewPromise.resolve(1);
const rejected = NewPromise.reject(-1);
const resolved1 = NewPromise.resolve(17);
const p = NewPromise.all([resolved, resolved1, rejected]);
p.then((result) => {
console.log('result', result)
}).catch(err => {
console.log('err', err)
})
复制代码
allSettled
测试const resolved = NewPromise.resolve(1);
const rejected = NewPromise.reject(-1);
const resolved1 = NewPromise.resolve(17);
const p = NewPromise.allSettled([resolved, resolved1, rejected]);
p.then((result) => {
console.log('result', result)
})
复制代码
/*
* @Author: detanx
* @Date: 2020-05-11 17:39:52
* @Last Modified by: detanx
* @Last Modified time: 2020-05-11 17:39:52
*/
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
const NewPromise = function(executor) {
const _this = this;
_this.status = PENDING;
_this.data = undefined;
_this.onResolvedCallback = [];
_this.onRejectedCallback = [];
// 成功
function resolve(value) {
if (value instanceof Promise) {
return value.then(resolve, reject)
}
setTimeout(function() { // 异步执行全部的回调函数
if (_this.status === PENDING) {
_this.status = FULFILLED;
_this.data = value;
_this.onResolvedCallback.forEach(callback => callback(value));
}
})
}
// 失败
function reject(reason) {
setTimeout(function() { // 异步执行全部的回调函数
if (_this.status === PENDING) {
_this.status = REJECTED;
_this.data = reason;
_this.onRejectedCallback.forEach(callback => callback(reason));
}
})
}
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// then
NewPromise.prototype.then = function(onResolved, onRejected) {
const _this = this;
if ( typeof onResolved !== 'function') {
onResolved = function(value) { return value }
}
if ( typeof onRejected !== 'function') {
onRejected = function(reason) { throw reason }
}
// 公共判断
const common = function (data, resolve, reject) {
// 考虑到有可能throw,咱们将其包在try/catch块里
try {
let value = _this.status === FULFILLED
? onResolved(data)
: onRejected(data)
if( value instanceof Promise) {
value.then(resolve, reject)
}
resolve(value)
} catch (error) {
reject(error)
}
}
// 公共判断
const pendingCommon = function (data, flag, resolve, reject) {
// 考虑到有可能throw,咱们将其包在try/catch块里
try {
let value = flag === FULFILLED
? onResolved(data)
: onRejected(data)
if( value instanceof Promise) {
value.then(resolve, reject)
}
resolve(value)
} catch (error) {
reject(error)
}
}
if (_this.status === PENDING) {
return new NewPromise(function(resolve, reject) {
_this.onResolvedCallback.push((value) => {
pendingCommon(value, FULFILLED, resolve, reject);
})
_this.onRejectedCallback.push((reason) => {
pendingCommon(reason, REJECTED, resolve, reject);
})
})
} else { // resolve / reject
return new NewPromise(function (resolve, reject) {
setTimeout(function () {
common(_this.data, resolve, reject)
})
})
}
}
NewPromise.resolve = function(value) {
if (value instanceof Promise) return value;
if (value === null) return null;
// 判断若是是promise
if (typeof value === 'object' || typeof value === 'function') {
try {
// 判断是否有then方法
let then = value.then;
if (typeof then === 'function') {
return new NewPromise(then.call(value)); // 执行value方法
}
} catch (e) {
return new NewPromise( (resolve, reject) =>{
reject(e);
});
}
}
return new NewPromise( (resolve, reject) =>{
resolve(value);
});
}
NewPromise.reject = function(value) {
if (value instanceof Promise) return value;
if (value === null) return null;
// 判断若是是promise
if (typeof value === 'object' || typeof value === 'function') {
try {
// 判断是否有then方法
let then = value.then;
if (typeof then === 'function') {
return new NewPromise(then.call(value)); // 执行value方法
}
} catch (e) {
return new NewPromise( (resolve, reject) =>{
reject(e);
});
}
}
return new NewPromise( (resolve, reject) =>{
reject(value);
});
}
// catch方法
NewPromise.prototype.catch = function(onRejected) {
return this.then(null, onRejected)
}
// defered
NewPromise.deferred = function() {
const dfd = {}
dfd.promise = new NewPromise(function(resolve, reject) {
dfd.resolve = resolve
dfd.reject = reject
})
return dfd
}
// all
NewPromise.all = function(promises) {
return new NewPromise(function(resolve, reject) {
const result = []
promises = Array.isArray(promises) ? promises : []
const len = promises.length - 1;
promises.forEach((promise, index) => {
promise.then(value => {
result.push(value)
if(index === len) {
resolve(result)
}
}, reject)
})
})
}
// race
NewPromise.race = function (promises) {
return new NewPromise((resolve, reject) => {
promises = Array.isArray(promises) ? promises : []
promises.forEach(promise => {
promise.then(resolve, reject)
})
})
}
// allSettled
NewPromise.allSettled = function (promises) {
return new NewPromise((resolve, reject) => {
promises = Array.isArray(promises) ? promises : []
let len = promises.length;
const argslen = len;
if (len === 0) return resolve([]);
let args = Array.prototype.slice.call(promises);
function resolvePromise(index, value) {
if(typeof value === 'object') {
const then = value.then;
if(typeof then === 'function'){
then.call(value, function(val) {
args[index] = { status: 'fulfilled', value: val};
if(--len === 0) {
resolve(args);
}
}, function(e) {
args[index] = { status: 'rejected', reason: e };
if(--len === 0) {
reject(args);
}
})
}
}
}
for(let i = 0; i < argslen; i++){
resolvePromise(i, args[i]);
}
})
}
// 测试
// const promise = new NewPromise(function(resolve, reject) {
// console.log('ss', 11)
// // resolve(123)
// reject('errr')
// // throw 'ree'
// })
// promise.catch(val => {
// console.log('val', val)
// })
// const promise1 = new NewPromise(function(resolve, reject) {
// console.log('ss', 11)
// resolve(123)
// // reject('errr')
// })
// const rejected = NewPromise.reject(-1);
// rejected.catch(val => {
// console.log('rejected', val)
// })
// console.log('resolved', resolved)
const resolved = NewPromise.resolve(1);
const rejected = NewPromise.reject(-1);
const resolved1 = NewPromise.resolve(17);
const p = NewPromise.all([resolved, resolved1, rejected]);
p.then((result) => {
console.log('result', result)
}).catch(err => {
console.log('err', err)
})
复制代码
阮一峰 ECMAScript 6 入门
22 道高频 JavaScript 手写面试题及答案es6