返回
轻量级前端Promise库 Promiz 精妙解析
前端
2024-01-02 10:37:01
前言
在上一篇文章[译]前端基础知识储备——Promise/A+规范中,我们介绍了Promise/A+规范的具体条目。在本文中,我们选择了一个具体的Promise库——Promiz,让大家来看一下它的内部代码是如何运作的。Promiz是一个体积很小的Promise库(官方介绍约为913字节),但它功能齐全,符合Promise/A+规范。
Promiz源代码解析
Promiz的源代码非常简单,只有不到100行代码。我们一起来看一下它的源代码:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Promiz = factory());
}(this, (function () { 'use strict';
/**
* @description 创建一个新的Promise实例
* @param {Function} executor 执行器函数
*/
function Promiz(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function');
}
// Promise状态,初始为pending
this.status = 'pending';
// Promise结果值
this.value = undefined;
// Promise拒绝原因
this.reason = undefined;
// 存储成功回调函数的数组
this.onFulfilledCallbacks = [];
// 存储失败回调函数的数组
this.onRejectedCallbacks = [];
// 执行器函数,立即执行
try {
executor(resolve.bind(this), reject.bind(this));
} catch (error) {
reject.call(this, error);
}
}
/**
* @description 将Promise状态改为fulfilled,并执行成功回调函数
* @param {*} value Promise结果值
*/
function resolve(value) {
if (this.status !== 'pending') {
return;
}
this.status = 'fulfilled';
this.value = value;
// 执行成功回调函数
this.onFulfilledCallbacks.forEach(function (callback) {
callback(value);
});
}
/**
* @description 将Promise状态改为rejected,并执行失败回调函数
* @param {*} reason Promise拒绝原因
*/
function reject(reason) {
if (this.status !== 'pending') {
return;
}
this.status = 'rejected';
this.reason = reason;
// 执行失败回调函数
this.onRejectedCallbacks.forEach(function (callback) {
callback(reason);
});
}
/**
* @description 添加成功回调函数
* @param {Function} callback 成功回调函数
* @returns {Promiz} 返回当前Promise实例
*/
Promiz.prototype.then = function (onFulfilled, onRejected) {
var self = this;
// 返回一个新的Promise实例
return new Promiz(function (resolve, reject) {
// 将成功回调函数添加到数组中
self.onFulfilledCallbacks.push(function (value) {
// 如果成功回调函数不为null,则执行该函数
if (typeof onFulfilled === 'function') {
try {
// 将成功回调函数的返回值作为新Promise的结果值
var result = onFulfilled(value);
// 如果返回值是Promise,则将该Promise的最终结果作为新Promise的结果值
if (result instanceof Promiz) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
} else {
// 如果成功回调函数为null,则将Promise结果值作为新Promise的结果值
resolve(value);
}
});
// 将失败回调函数添加到数组中
self.onRejectedCallbacks.push(function (reason) {
// 如果失败回调函数不为null,则执行该函数
if (typeof onRejected === 'function') {
try {
// 将失败回调函数的返回值作为新Promise的结果值
var result = onRejected(reason);
// 如果返回值是Promise,则将该Promise的最终结果作为新Promise的结果值
if (result instanceof Promiz) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
} else {
// 如果失败回调函数为null,则将Promise拒绝原因作为新Promise的拒绝原因
reject(reason);
}
});
});
};
/**
* @description 添加失败回调函数
* @param {Function} callback 失败回调函数
* @returns {Promiz} 返回当前Promise实例
*/
Promiz.prototype.catch = function (onRejected) {
return this.then(null, onRejected);
};
/**
* @description 添加finally回调函数
* @param {Function} callback finally回调函数
* @returns {Promiz} 返回当前Promise实例
*/
Promiz.prototype.finally = function (callback) {
return this.then(function (value) {
return Promiz.resolve(callback()).then(function () {
return value;
});
}, function (reason) {
return Promiz.resolve(callback()).then(function () {
throw reason;
});
});
};
/**
* @description 创建一个成功状态的Promise实例
* @param {*} value Promise结果值
* @returns {Promiz} 返回一个新的Promise实例
*/
Promiz.resolve = function (value) {
return new Promiz(function (resolve) {
resolve(value);
});
};
/**
* @description 创建一个失败状态的Promise实例
* @param {*} reason Promise拒绝原因
* @returns {Promiz} 返回一个新的Promise实例
*/
Promiz.reject = function (reason) {
return new Promiz(function (resolve, reject) {
reject(reason);
});
};
/**
* @description 判断一个值是否为Promise实例
* @param {*} value 要判断的值
* @returns {boolean} 如果是Promise实例,则返回true,否则返回false
*/
Promiz.isPromiz = function (value) {
return value instanceof Promiz;
};
/**
* @description 执行所有Promise实例的then方法,并将结果收集到一个数组中
* @param {Array} promises Promise实例数组
* @returns {Promiz} 返回一个新的Promise实例,该实例的结果值是所有Promise实例结果值的数组
*/
Promiz.all = function (promises) {
return new Promiz(function (resolve, reject) {
var result = [];
var count = 0;
promises.forEach(function (promise, index) {
promise.then(function (value) {
result[index] = value;
count++;
if (count === promises.length) {
resolve(result);
}
}, function (reason) {
reject(reason);
});
});
});
};
/**
* @description 执行所有Promise实例的then方法,并将第一个结果值作为新Promise的结果值
* @param {Array} promises Promise实例数组
* @returns {Promiz} 返回一个新的Promise实例,该实例的结果值是第一个Promise实例的结果值
*/
Promiz.race = function (promises) {
return new Promiz(function (resolve, reject) {
promises.forEach(function (promise) {
promise.then(resolve, reject);
});
});
};
return Promiz;
})));
从上面的源代码中,我们可以看到Promiz的实现非常简单,它主要包括以下几个部分:
- 构造函数Promiz :用于创建新的Promise实例。
- resolve方法 :将Promise状态改为fulfilled,并执行成功回调函数。
- reject方法 :将Promise状态改为rejected,并执行失败回调函数。
- then方法 :