深入了解Promise机制并使用JS实现一个Promise(二)

news/2024/10/22 22:55:31/

接着上一篇深入了解Promise机制并使用JS实现一个Promise(一)文章接着使用js来实现一个xpromise

已实现效果

经过上一篇文章我们已近得到下面的代码,实现了promise的状态、值、以及then方法的实现。下面我们接着来实现promise中其他的方法

class XPromise {constructor(handle) {// 用来记录当前XPromise的状态 pending | fulfilled | rejectedthis["[[PromiseState]]"] = "pending";// 用来记录当前XPromise的值this["[[PromiseResult]]"] = undefined;this.resolveFnList = [];this.rejectFnList = [];// 使用否箭头函数规避this问题, 否则就得这里bind一下// handle(this.#resolve.bind(this), this.#reject.bind(this))handle(this.#resolve, this.#reject);}// 对标promise中的resolve#resolve = (val) => {this["[[PromiseState]]"] = "fulfilled";this["[[PromiseResult]]"] = val;// 将his.resolveFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.resolveFnList, val)};// 对标promise中的reject#reject = (error) => {this["[[PromiseState]]"] = "rejected";this["[[PromiseResult]]"] = error;// 将执行this.rejectFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.rejectFnList, error)};// 将.then函数接受的onResolve和onReject函数放在微任务中执行#observerAndExecuteFn = (fnList, promiseResult) => {const executeFnList = () => {let itemFn = null;while (fnList.length) {itemFn = fnList.shift();itemFn(promiseResult);}};const targetNode = document.getElementsByTagName("body")[0];const observe = new MutationObserver(executeFnList);observe.observe(targetNode, {attributes: true,});targetNode.setAttribute("x-promise", "watch");};/*** xpromise实例方法* 1. 在promise resolve/reject之后执行onResolved/onReject* 2. 返回一个新的xpromise实例(新的实例而不是原来的xpromise实例)* @param {*} onResolved * @param {*} onReject * @returns */then = (onResolved, onReject) => {// 返回一个新的xpromise实例return new XPromise((resolve, reject) => {// 在这里需要把当前这个promise的结果拿到// resolveFn是需要push到函数队列中的,接受当前promise实例结果的值const resolveFn = (val) => {const result = onResolved && onResolved(val);if (result instanceof XPromise) {// result 既然是xpromise实例// 那这个xpromise的结果就可以从.then中获取result.then((val) => resolve(val));} else {resolve(result);}};this.resolveFnList.push(resolveFn);const rejectFn = (error) => {onReject && onReject(error);reject(error);};this.rejectFnList.push(rejectFn);});};
}export default XPromise;

Promise实例catch方法

定义

Promise 实例的 catch() 方法用于注册一个在 promise 被拒绝时调用的函数。它会立即返回一个等效的 Promise 对象,这可以允许你链式调用其他 promise 的方法。此方法是 Promise.prototype.then(undefined, onRejected) 的一种简写形式。
我们看下原生promise.catch的效果
在这里插入图片描述

实现

可以看到,一个是返回新的promise,另一个是可以catch住之前的onReject。而.catch实际上是promise.then(null, onReject)的一个简写,而我们在之前已经完整实现了promise.then方法,所以只需要直接``return this.then(null, onReject)即可。完整代码如下:

class XPromise {constructor(handle) {// 用来记录当前XPromise的状态 pending | fulfilled | rejectedthis["[[PromiseState]]"] = "pending";// 用来记录当前XPromise的值this["[[PromiseResult]]"] = undefined;this.resolveFnList = [];this.rejectFnList = [];// 使用否箭头函数规避this问题, 否则就得这里bind一下// handle(this.#resolve.bind(this), this.#reject.bind(this))handle(this.#resolve, this.#reject);}// 对标promise中的resolve#resolve = (val) => {this["[[PromiseState]]"] = "fulfilled";this["[[PromiseResult]]"] = val;// 将his.resolveFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.resolveFnList, val)};// 对标promise中的reject#reject = (error) => {this["[[PromiseState]]"] = "rejected";this["[[PromiseResult]]"] = error;// 将执行this.rejectFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.rejectFnList, error)};// 将.then函数接受的onResolve和onReject函数放在微任务中执行#observerAndExecuteFn = (fnList, promiseResult) => {const executeFnList = () => {let itemFn = null;while (fnList.length) {itemFn = fnList.shift();itemFn(promiseResult);}};const targetNode = document.getElementsByTagName("body")[0];const observe = new MutationObserver(executeFnList);observe.observe(targetNode, {attributes: true,});targetNode.setAttribute("x-promise", "watch");};/*** xpromise实例方法* 1. 在promise resolve/reject之后执行onResolved/onReject* 2. 返回一个新的xpromise实例(新的实例而不是原来的xpromise实例)* @param {*} onResolved * @param {*} onReject * @returns */then = (onResolved, onReject) => {// 返回一个新的xpromise实例return new XPromise((resolve, reject) => {// 在这里需要把当前这个promise的结果拿到// resolveFn是需要push到函数队列中的,接受当前promise实例结果的值const resolveFn = (val) => {const result = onResolved && onResolved(val);if (result instanceof XPromise) {// result 既然是xpromise实例// 那这个xpromise的结果就可以从.then中获取result.then((val) => resolve(val));} else {resolve(result);}};this.resolveFnList.push(resolveFn);const rejectFn = (error) => {onReject && onReject(error);reject(error);};this.rejectFnList.push(rejectFn);});};// promise.then(null, onReject)的简写catch = (onReject) => {return this.then(undefined, onReject)}
}export default XPromise;

运行的效果如下所示:
在这里插入图片描述

Promise实例finnal方法

定义

finally() 方法返回一个 Promise。在 promise 结束时,无论结果是 fulfilled 或者是 rejected,都会执行指定的回调函数。这为在 Promise 是否成功完成后都需要执行的代码提供了一种方式。这避免了同样的语句需要在 then() 和 catch() 中各写一次的情况。
在这里插入图片描述
可以看到finally有如下几个特征

  1. 接受一个函数作为参数,但该函数没有参数
  2. 没有返回
  3. 下一个promise.then对象接受的是finally的上一个then的返回

实现

class XPromise {constructor(handle) {// 用来记录当前XPromise的状态 pending | fulfilled | rejectedthis["[[PromiseState]]"] = "pending";// 用来记录当前XPromise的值this["[[PromiseResult]]"] = undefined;this.resolveFnList = [];this.rejectFnList = [];// 使用否箭头函数规避this问题, 否则就得这里bind一下// handle(this.#resolve.bind(this), this.#reject.bind(this))handle(this.#resolve, this.#reject);}// 对标promise中的resolve#resolve = (val) => {this["[[PromiseState]]"] = "fulfilled";this["[[PromiseResult]]"] = val;// 将his.resolveFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.resolveFnList, val)};// 对标promise中的reject#reject = (error) => {this["[[PromiseState]]"] = "rejected";this["[[PromiseResult]]"] = error;// 将执行this.rejectFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.rejectFnList, error)};// 将.then函数接受的onResolve和onReject函数放在微任务中执行#observerAndExecuteFn = (fnList, promiseResult) => {const executeFnList = () => {let itemFn = null;while (fnList.length) {itemFn = fnList.shift();itemFn(promiseResult);}};const targetNode = document.getElementsByTagName("body")[0];const observe = new MutationObserver(executeFnList);observe.observe(targetNode, {attributes: true,});targetNode.setAttribute("x-promise", "watch");};/*** xpromise实例方法* 1. 在promise resolve/reject之后执行onResolved/onReject* 2. 返回一个新的xpromise实例(新的实例而不是原来的xpromise实例)* @param {*} onResolved * @param {*} onReject * @returns */then = (onResolved, onReject) => {// 返回一个新的xpromise实例return new XPromise((resolve, reject) => {// 在这里需要把当前这个promise的结果拿到// resolveFn是需要push到函数队列中的,接受当前promise实例结果的值const resolveFn = (val) => {const result = onResolved && onResolved(val);if (result instanceof XPromise) {// result 既然是xpromise实例// 那这个xpromise的结果就可以从.then中获取result.then((val) => resolve(val));} else {resolve(result);}};this.resolveFnList.push(resolveFn);const rejectFn = (error) => {onReject && onReject(error);reject(error);};this.rejectFnList.push(rejectFn);});};// promise.then(null, onReject)的简写catch = (onReject) => {return this.then(undefined, onReject)}/*** 本质上就是个高阶函数* 是对this.then函数的封装,接受一个fn,* 执行fn之后就走正常的then逻辑即可* 可以理解为对this.then的升阶接受一个函数参数* 高阶函数,类似HOC执行this.then之前执行fn* @param {*} fn * @returns */finally = (fn) => {// finally 函数就是对 this.then 函数包装了一下// 本质还是执行this.then函数,不过在执行原本this.then函数中的onResolved和onReject之前先执行fnreturn this.then(// 这个val就是上一个then的值val => {// 执行传递进来的fnfn && fn();if (val instanceof XPromise) {// 上一个then返回的是promise 通过then获取上一个promise的值,再resolve给下一个then即可return val.then(v => XPromise.resolve(v))} else {return XPromise.resolve(val)}},// 这个error就是上一个then的值error => {fn && fn();if (error instanceof XPromise) {return error.catch(v => XPromise.reject(v))} else {return XPromise.reject(error)}})}/*** 根据参数的类别判断* 非promise:返回一个新的`promise`实例* promise:直接返回改promise即可* @param {*} val * @returns */static resolve = (val) => {if (val instanceof XPromise) {return val} else {return new XPromise((resolve) => {resolve(val)})}}static reject = (error) => {return new XPromise((undefined, reject) => {reject(error)})}static race = (promiseList) => {let execute = falsereturn new XPromise((resolve, reject) => {promiseList.forEach(promiseItem => {// 每个promiseItem都是xpromise 那就可以通过.then获取值promiseItem.then(val => {if (execute) return;resolve(val)execute = true}, error => {if (execute) return;reject(error)execute = true})});})}static all = (promiseList) => {return new XPromise((resolve, reject) => {// 1. 用于存储每个promise的结果// 2. 返回的promise结果顺序与接入的promise顺序相同故使用new Array(promiseList.length);的方式存结果const result = new Array(promiseList.length);// 用于计数运行了多个个promiselet num = 0promiseList.forEach((promiseItem, index) => {// 每一个结果都是一个对象result[index] = {}promiseItem.then(val => {// 更新该位置的promise信息result[index]['status'] = "fulfilled"result[index]['value'] = val// 如果都运行完了就直接resolve// 证明所有promise都是成功的, 整个promise状态也是成功的num ++if (num >= promiseList.length) resolve(result)}, error => {// 在promise数组中有某个promise失败了// 整个promise状态算失败,reject失败最快的那个即可reject(error)})})})}static allSettled = (promiseList) => {return new XPromise((resolve, reject) => {// 1. 用于存储每个promise的结果// 2. 返回的promise结果顺序与接入的promise顺序相同故使用new Array(promiseList.length);的方式存结果const result = new Array(promiseList.length);// 用于计数运行了多个个promiselet num = 0promiseList.forEach((promiseItem, index) => {// 每一个结果都是一个对象result[index] = {};promiseItem.then((val)=> {// 更新该位置的promise信息result[index]['status'] = "fulfilled"result[index]['value'] = val// 如果都运行完了就直接resolvenum ++if (num >= promiseList.length) resolve(result)}, error => {// 更新该位置的promise信息result[index]['status'] = "rejected"result[index]['reason'] = error// 如果都运行完了就直接resolvenum ++if (num >= promiseList.length) resolve(result)})})})}static any = (promiseList) => {return new XPromise((resolve, reject) => {// 1. 用于存储每个promise的结果// 2. 返回的快的promise结果先push入数组const result = []// 用于计数运行了多个个promiselet num = 0// 等每个promise都处理完了,根据每个promise结果决定整个promise的结果const dealResult = () => {// 看能否找到一个成功的promise,先找到的也就是返回最快的promiseconst successPromise = result.find(resultItem => resultItem.status === 'fulfilled')if (successPromise) {resolve(successPromise)} else {throw new Error('All promises were rejected')}}promiseList.forEach((promiseItem, index) => {// 每一个结果都是一个对象const resultItem = {}promiseItem.then((val)=> {// 更新该位置的promise信息resultItem['status'] = "fulfilled"resultItem['value'] = valresult.push(resultItem)// 如果都运行完了再判断整个Promise的状态num ++if (num >= promiseList.length) dealResult()}, error => {// 更新该位置的promise信息resultItem['status'] = "rejected"resultItem['value'] = errorresult.push(resultItem)// 如果都运行完了再判断整个Promise的状态num ++if (num >= promiseList.length) dealResult()})})})}}export default XPromise;

执行效果如下:
在这里插入图片描述

Promise.resolve 静态方法

定义

Promise.resolve() 静态方法将给定的值转换为一个 Promise。如果该值本身就是一个 Promise,那么该 Promise 将被返回;
在这里插入图片描述

实现

我们分析,首先Promise.resolve()函数接受一个值根据该值的类型做返回即可:

  1. 非promise:返回一个新的promise实例
  2. promise:直接返回改promise即可
    完整代码如下:
class XPromise {constructor(handle) {// 用来记录当前XPromise的状态 pending | fulfilled | rejectedthis["[[PromiseState]]"] = "pending";// 用来记录当前XPromise的值this["[[PromiseResult]]"] = undefined;this.resolveFnList = [];this.rejectFnList = [];// 使用否箭头函数规避this问题, 否则就得这里bind一下// handle(this.#resolve.bind(this), this.#reject.bind(this))handle(this.#resolve, this.#reject);}// 对标promise中的resolve#resolve = (val) => {this["[[PromiseState]]"] = "fulfilled";this["[[PromiseResult]]"] = val;// 将his.resolveFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.resolveFnList, val)};// 对标promise中的reject#reject = (error) => {this["[[PromiseState]]"] = "rejected";this["[[PromiseResult]]"] = error;// 将执行this.rejectFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.rejectFnList, error)};// 将.then函数接受的onResolve和onReject函数放在微任务中执行#observerAndExecuteFn = (fnList, promiseResult) => {const executeFnList = () => {let itemFn = null;while (fnList.length) {itemFn = fnList.shift();itemFn(promiseResult);}};const targetNode = document.getElementsByTagName("body")[0];const observe = new MutationObserver(executeFnList);observe.observe(targetNode, {attributes: true,});targetNode.setAttribute("x-promise", "watch");};/*** xpromise实例方法* 1. 在promise resolve/reject之后执行onResolved/onReject* 2. 返回一个新的xpromise实例(新的实例而不是原来的xpromise实例)* @param {*} onResolved * @param {*} onReject * @returns */then = (onResolved, onReject) => {// 返回一个新的xpromise实例return new XPromise((resolve, reject) => {// 在这里需要把当前这个promise的结果拿到// resolveFn是需要push到函数队列中的,接受当前promise实例结果的值const resolveFn = (val) => {const result = onResolved && onResolved(val);if (result instanceof XPromise) {// result 既然是xpromise实例// 那这个xpromise的结果就可以从.then中获取result.then((val) => resolve(val));} else {resolve(result);}};this.resolveFnList.push(resolveFn);const rejectFn = (error) => {onReject && onReject(error);reject(error);};this.rejectFnList.push(rejectFn);});};// promise.then(null, onReject)的简写catch = (onReject) => {return this.then(undefined, onReject)}/*** 根据参数的类别判断* 非promise:返回一个新的`promise`实例* promise:直接返回改promise即可* @param {*} val * @returns */static resolve = (val) => {if (val instanceof XPromise) {return val} else {return new XPromise((resolve) => {resolve(val)})}}
}export default XPromise;

代码执行效果如下:
在这里插入图片描述

Promise.reject静态方法

定义

Promise.reject() 静态方法返回一个已拒绝(rejected)的 Promise 对象,拒绝原因为给定的参数。
在这里插入图片描述

实现

Promise.rejectPromise.resolve整体很像这里需要注意的是,根据MDN上的描述,我们知道返回的一定是一个新的promise对象,所以就不用对入参类型进行判断了
在这里插入图片描述
整体代码如下:

class XPromise {constructor(handle) {// 用来记录当前XPromise的状态 pending | fulfilled | rejectedthis["[[PromiseState]]"] = "pending";// 用来记录当前XPromise的值this["[[PromiseResult]]"] = undefined;this.resolveFnList = [];this.rejectFnList = [];// 使用否箭头函数规避this问题, 否则就得这里bind一下// handle(this.#resolve.bind(this), this.#reject.bind(this))handle(this.#resolve, this.#reject);}// 对标promise中的resolve#resolve = (val) => {this["[[PromiseState]]"] = "fulfilled";this["[[PromiseResult]]"] = val;// 将his.resolveFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.resolveFnList, val)};// 对标promise中的reject#reject = (error) => {this["[[PromiseState]]"] = "rejected";this["[[PromiseResult]]"] = error;// 将执行this.rejectFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.rejectFnList, error)};// 将.then函数接受的onResolve和onReject函数放在微任务中执行#observerAndExecuteFn = (fnList, promiseResult) => {const executeFnList = () => {let itemFn = null;while (fnList.length) {itemFn = fnList.shift();itemFn(promiseResult);}};const targetNode = document.getElementsByTagName("body")[0];const observe = new MutationObserver(executeFnList);observe.observe(targetNode, {attributes: true,});targetNode.setAttribute("x-promise", "watch");};/*** xpromise实例方法* 1. 在promise resolve/reject之后执行onResolved/onReject* 2. 返回一个新的xpromise实例(新的实例而不是原来的xpromise实例)* @param {*} onResolved * @param {*} onReject * @returns */then = (onResolved, onReject) => {// 返回一个新的xpromise实例return new XPromise((resolve, reject) => {// 在这里需要把当前这个promise的结果拿到// resolveFn是需要push到函数队列中的,接受当前promise实例结果的值const resolveFn = (val) => {const result = onResolved && onResolved(val);if (result instanceof XPromise) {// result 既然是xpromise实例// 那这个xpromise的结果就可以从.then中获取result.then((val) => resolve(val));} else {resolve(result);}};this.resolveFnList.push(resolveFn);const rejectFn = (error) => {onReject && onReject(error);reject(error);};this.rejectFnList.push(rejectFn);});};// promise.then(null, onReject)的简写catch = (onReject) => {return this.then(undefined, onReject)}/*** 根据参数的类别判断* 非promise:返回一个新的`promise`实例* promise:直接返回改promise即可* @param {*} val * @returns */static resolve = (val) => {if (val instanceof XPromise) {return val} else {return new XPromise((resolve) => {resolve(val)})}}static reject = (error) => {return new XPromise((undefined, reject) => {reject(error)})}
}export default XPromise;

代码执行效果如下所示:
在这里插入图片描述

Promise.race静态方法

定义

Promise.race() 静态方法接受一个 promise 可迭代对象作为输入,并返回一Promise。这个返回的 promise 会随着第一个 promise 的敲定而敲定。我们看原生的Promise.all的效果如下:
在这里插入图片描述

实现

思路是接受一个promise数组,数组中的每个promise并发执行,谁最先得到结果,将结果返回resolve/reject掉即可

class XPromise {constructor(handle) {// 用来记录当前XPromise的状态 pending | fulfilled | rejectedthis["[[PromiseState]]"] = "pending";// 用来记录当前XPromise的值this["[[PromiseResult]]"] = undefined;this.resolveFnList = [];this.rejectFnList = [];// 使用否箭头函数规避this问题, 否则就得这里bind一下// handle(this.#resolve.bind(this), this.#reject.bind(this))handle(this.#resolve, this.#reject);}// 对标promise中的resolve#resolve = (val) => {this["[[PromiseState]]"] = "fulfilled";this["[[PromiseResult]]"] = val;// 将his.resolveFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.resolveFnList, val)};// 对标promise中的reject#reject = (error) => {this["[[PromiseState]]"] = "rejected";this["[[PromiseResult]]"] = error;// 将执行this.rejectFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.rejectFnList, error)};// 将.then函数接受的onResolve和onReject函数放在微任务中执行#observerAndExecuteFn = (fnList, promiseResult) => {const executeFnList = () => {let itemFn = null;while (fnList.length) {itemFn = fnList.shift();itemFn(promiseResult);}};const targetNode = document.getElementsByTagName("body")[0];const observe = new MutationObserver(executeFnList);observe.observe(targetNode, {attributes: true,});targetNode.setAttribute("x-promise", "watch");};/*** xpromise实例方法* 1. 在promise resolve/reject之后执行onResolved/onReject* 2. 返回一个新的xpromise实例(新的实例而不是原来的xpromise实例)* @param {*} onResolved * @param {*} onReject * @returns */then = (onResolved, onReject) => {// 返回一个新的xpromise实例return new XPromise((resolve, reject) => {// 在这里需要把当前这个promise的结果拿到// resolveFn是需要push到函数队列中的,接受当前promise实例结果的值const resolveFn = (val) => {const result = onResolved && onResolved(val);if (result instanceof XPromise) {// result 既然是xpromise实例// 那这个xpromise的结果就可以从.then中获取result.then((val) => resolve(val));} else {resolve(result);}};this.resolveFnList.push(resolveFn);const rejectFn = (error) => {onReject && onReject(error);reject(error);};this.rejectFnList.push(rejectFn);});};// promise.then(null, onReject)的简写catch = (onReject) => {return this.then(undefined, onReject)}/*** 根据参数的类别判断* 非promise:返回一个新的`promise`实例* promise:直接返回改promise即可* @param {*} val * @returns */static resolve = (val) => {if (val instanceof XPromise) {return val} else {return new XPromise((resolve) => {resolve(val)})}}static reject = (error) => {return new XPromise((undefined, reject) => {reject(error)})}static race = (promiseList) => {let execute = falsereturn new XPromise((resolve, reject) => {promiseList.forEach(promiseItem => {// 每个promiseItem都是xpromise 那就可以通过.then获取值promiseItem.then(val => {if (execute) return;resolve(val)execute = true}, error => {if (execute) return;reject(error)execute = true})});})}
}export default XPromise;

代码执行效果如下:
在这里插入图片描述
在这里插入图片描述

Promise.all静态方法

定义

Promise.all() 静态方法接受一个 Promise 可迭代对象作为输入,并返回一个 Promise。当所有输入的 Promise 都被兑现时,返回的 Promise 也将被兑现(即使传入的是一个空的可迭代对象),并返回一个包含所有兑现值的数组。如果输入的任何 Promise 被拒绝,则返回的 Promise 将被拒绝,并带有第一个被拒绝的原因。
在这里插入图片描述

实现

class XPromise {constructor(handle) {// 用来记录当前XPromise的状态 pending | fulfilled | rejectedthis["[[PromiseState]]"] = "pending";// 用来记录当前XPromise的值this["[[PromiseResult]]"] = undefined;this.resolveFnList = [];this.rejectFnList = [];// 使用否箭头函数规避this问题, 否则就得这里bind一下// handle(this.#resolve.bind(this), this.#reject.bind(this))handle(this.#resolve, this.#reject);}// 对标promise中的resolve#resolve = (val) => {this["[[PromiseState]]"] = "fulfilled";this["[[PromiseResult]]"] = val;// 将his.resolveFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.resolveFnList, val)};// 对标promise中的reject#reject = (error) => {this["[[PromiseState]]"] = "rejected";this["[[PromiseResult]]"] = error;// 将执行this.rejectFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.rejectFnList, error)};// 将.then函数接受的onResolve和onReject函数放在微任务中执行#observerAndExecuteFn = (fnList, promiseResult) => {const executeFnList = () => {let itemFn = null;while (fnList.length) {itemFn = fnList.shift();itemFn(promiseResult);}};const targetNode = document.getElementsByTagName("body")[0];const observe = new MutationObserver(executeFnList);observe.observe(targetNode, {attributes: true,});targetNode.setAttribute("x-promise", "watch");};/*** xpromise实例方法* 1. 在promise resolve/reject之后执行onResolved/onReject* 2. 返回一个新的xpromise实例(新的实例而不是原来的xpromise实例)* @param {*} onResolved * @param {*} onReject * @returns */then = (onResolved, onReject) => {// 返回一个新的xpromise实例return new XPromise((resolve, reject) => {// 在这里需要把当前这个promise的结果拿到// resolveFn是需要push到函数队列中的,接受当前promise实例结果的值const resolveFn = (val) => {const result = onResolved && onResolved(val);if (result instanceof XPromise) {// result 既然是xpromise实例// 那这个xpromise的结果就可以从.then中获取result.then((val) => resolve(val));} else {resolve(result);}};this.resolveFnList.push(resolveFn);const rejectFn = (error) => {onReject && onReject(error);reject(error);};this.rejectFnList.push(rejectFn);});};// promise.then(null, onReject)的简写catch = (onReject) => {return this.then(undefined, onReject)}/*** 根据参数的类别判断* 非promise:返回一个新的`promise`实例* promise:直接返回改promise即可* @param {*} val * @returns */static resolve = (val) => {if (val instanceof XPromise) {return val} else {return new XPromise((resolve) => {resolve(val)})}}static reject = (error) => {return new XPromise((undefined, reject) => {reject(error)})}static race = (promiseList) => {let execute = falsereturn new XPromise((resolve, reject) => {promiseList.forEach(promiseItem => {// 每个promiseItem都是xpromise 那就可以通过.then获取值promiseItem.then(val => {if (execute) return;resolve(val)execute = true}, error => {if (execute) return;reject(error)execute = true})});})}static all = (promiseList) => {return new XPromise((resolve, reject) => {// 1. 用于存储每个promise的结果// 2. 返回的promise结果顺序与接入的promise顺序相同故使用new Array(promiseList.length);的方式存结果const result = new Array(promiseList.length);// 用于计数运行了多个个promiselet num = 0promiseList.forEach((promiseItem, index) => {// 每一个结果都是一个对象result[index] = {}promiseItem.then(val => {// 更新该位置的promise信息result[index]['status'] = "fulfilled"result[index]['value'] = val// 如果都运行完了就直接resolve// 证明所有promise都是成功的, 整个promise状态也是成功的num ++if (num >= promiseList.length) resolve(result)}, error => {// 在promise数组中有某个promise失败了// 整个promise状态算失败,reject失败最快的那个即可reject(error)})})})}static allSettled = (promiseList) => {return new XPromise((resolve, reject) => {// 1. 用于存储每个promise的结果// 2. 返回的promise结果顺序与接入的promise顺序相同故使用new Array(promiseList.length);的方式存结果const result = new Array(promiseList.length);// 用于计数运行了多个个promiselet num = 0promiseList.forEach((promiseItem, index) => {// 每一个结果都是一个对象result[index] = {};promiseItem.then((val)=> {// 更新该位置的promise信息result[index]['status'] = "fulfilled"result[index]['value'] = val// 如果都运行完了就直接resolvenum ++if (num >= promiseList.length) resolve(result)}, error => {// 更新该位置的promise信息result[index]['status'] = "rejected"result[index]['reason'] = error// 如果都运行完了就直接resolvenum ++if (num >= promiseList.length) resolve(result)})})})}
}export default XPromise;

代码执行效果如下:
在这里插入图片描述

Promise.allSettled静态方法

定义

Promise.allSettled() 静态方法将一个 Promise 可迭代对象作为输入,并返回一个单独的 Promise。当所有输入的 Promise 都已敲定时(包括传入空的可迭代对象时),返回的 Promise 将被兑现,并带有描述每个 Promise 结果的对象数组
在这里插入图片描述

实现

代码如下:

class XPromise {constructor(handle) {// 用来记录当前XPromise的状态 pending | fulfilled | rejectedthis["[[PromiseState]]"] = "pending";// 用来记录当前XPromise的值this["[[PromiseResult]]"] = undefined;this.resolveFnList = [];this.rejectFnList = [];// 使用否箭头函数规避this问题, 否则就得这里bind一下// handle(this.#resolve.bind(this), this.#reject.bind(this))handle(this.#resolve, this.#reject);}// 对标promise中的resolve#resolve = (val) => {this["[[PromiseState]]"] = "fulfilled";this["[[PromiseResult]]"] = val;// 将his.resolveFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.resolveFnList, val)};// 对标promise中的reject#reject = (error) => {this["[[PromiseState]]"] = "rejected";this["[[PromiseResult]]"] = error;// 将执行this.rejectFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.rejectFnList, error)};// 将.then函数接受的onResolve和onReject函数放在微任务中执行#observerAndExecuteFn = (fnList, promiseResult) => {const executeFnList = () => {let itemFn = null;while (fnList.length) {itemFn = fnList.shift();itemFn(promiseResult);}};const targetNode = document.getElementsByTagName("body")[0];const observe = new MutationObserver(executeFnList);observe.observe(targetNode, {attributes: true,});targetNode.setAttribute("x-promise", "watch");};/*** xpromise实例方法* 1. 在promise resolve/reject之后执行onResolved/onReject* 2. 返回一个新的xpromise实例(新的实例而不是原来的xpromise实例)* @param {*} onResolved * @param {*} onReject * @returns */then = (onResolved, onReject) => {// 返回一个新的xpromise实例return new XPromise((resolve, reject) => {// 在这里需要把当前这个promise的结果拿到// resolveFn是需要push到函数队列中的,接受当前promise实例结果的值const resolveFn = (val) => {const result = onResolved && onResolved(val);if (result instanceof XPromise) {// result 既然是xpromise实例// 那这个xpromise的结果就可以从.then中获取result.then((val) => resolve(val));} else {resolve(result);}};this.resolveFnList.push(resolveFn);const rejectFn = (error) => {onReject && onReject(error);reject(error);};this.rejectFnList.push(rejectFn);});};// promise.then(null, onReject)的简写catch = (onReject) => {return this.then(undefined, onReject)}/*** 根据参数的类别判断* 非promise:返回一个新的`promise`实例* promise:直接返回改promise即可* @param {*} val * @returns */static resolve = (val) => {if (val instanceof XPromise) {return val} else {return new XPromise((resolve) => {resolve(val)})}}static reject = (error) => {return new XPromise((undefined, reject) => {reject(error)})}static race = (promiseList) => {let execute = falsereturn new XPromise((resolve, reject) => {promiseList.forEach(promiseItem => {// 每个promiseItem都是xpromise 那就可以通过.then获取值promiseItem.then(val => {if (execute) return;resolve(val)execute = true}, error => {if (execute) return;reject(error)execute = true})});})}static allSettled = (promiseList) => {return new XPromise((resolve, reject) => {// 1. 用于存储每个promise的结果// 2. 返回的promise结果顺序与接入的promise顺序相同故使用new Array(promiseList.length);的方式存结果const result = new Array(promiseList.length);// 用于计数运行了多个个promiselet num = 0promiseList.forEach((promiseItem, index) => {// 每一个结果都是一个对象result[index] = {};promiseItem.then((val)=> {// 更新该位置的promise信息result[index]['status'] = "fulfilled"result[index]['value'] = val// 如果都运行完了就直接resolvenum ++if (num >= promiseList.length) resolve(result)}, error => {// 更新该位置的promise信息result[index]['status'] = "rejected"result[index]['reason'] = error// 如果都运行完了就直接resolvenum ++if (num >= promiseList.length) resolve(result)})})})}
}export default XPromise;

代码执行效果如下:
在这里插入图片描述

某种意义上Promise.allSettled方法也是弥补了Promise.all方法一旦有某一个promise被拒绝了就拿不到整个结果的缺陷

Promise.any静态方法

定义

Promise.any() 静态方法将一个 Promise 可迭代对象作为输入,并返回一个 Promise。当输入的任何一个 Promise 兑现时,这个返回的 Promise 将会兑现,并返回第一个兑现的值。当所有输入 Promise 都被拒绝(包括传递了空的可迭代对象)时,它会以一个包含拒绝原因数组的 AggregateError 拒绝。

在这里插入图片描述

实现

class XPromise {constructor(handle) {// 用来记录当前XPromise的状态 pending | fulfilled | rejectedthis["[[PromiseState]]"] = "pending";// 用来记录当前XPromise的值this["[[PromiseResult]]"] = undefined;this.resolveFnList = [];this.rejectFnList = [];// 使用否箭头函数规避this问题, 否则就得这里bind一下// handle(this.#resolve.bind(this), this.#reject.bind(this))handle(this.#resolve, this.#reject);}// 对标promise中的resolve#resolve = (val) => {this["[[PromiseState]]"] = "fulfilled";this["[[PromiseResult]]"] = val;// 将his.resolveFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.resolveFnList, val)};// 对标promise中的reject#reject = (error) => {this["[[PromiseState]]"] = "rejected";this["[[PromiseResult]]"] = error;// 将执行this.rejectFn(val)的时机放入微任务中执行this.#observerAndExecuteFn(this.rejectFnList, error)};// 将.then函数接受的onResolve和onReject函数放在微任务中执行#observerAndExecuteFn = (fnList, promiseResult) => {const executeFnList = () => {let itemFn = null;while (fnList.length) {itemFn = fnList.shift();itemFn(promiseResult);}};const targetNode = document.getElementsByTagName("body")[0];const observe = new MutationObserver(executeFnList);observe.observe(targetNode, {attributes: true,});targetNode.setAttribute("x-promise", "watch");};/*** xpromise实例方法* 1. 在promise resolve/reject之后执行onResolved/onReject* 2. 返回一个新的xpromise实例(新的实例而不是原来的xpromise实例)* @param {*} onResolved * @param {*} onReject * @returns */then = (onResolved, onReject) => {// 返回一个新的xpromise实例return new XPromise((resolve, reject) => {// 在这里需要把当前这个promise的结果拿到// resolveFn是需要push到函数队列中的,接受当前promise实例结果的值const resolveFn = (val) => {const result = onResolved && onResolved(val);if (result instanceof XPromise) {// result 既然是xpromise实例// 那这个xpromise的结果就可以从.then中获取result.then((val) => resolve(val));} else {resolve(result);}};this.resolveFnList.push(resolveFn);const rejectFn = (error) => {onReject && onReject(error);reject(error);};this.rejectFnList.push(rejectFn);});};// promise.then(null, onReject)的简写catch = (onReject) => {return this.then(undefined, onReject)}/*** 根据参数的类别判断* 非promise:返回一个新的`promise`实例* promise:直接返回改promise即可* @param {*} val * @returns */static resolve = (val) => {if (val instanceof XPromise) {return val} else {return new XPromise((resolve) => {resolve(val)})}}static reject = (error) => {return new XPromise((undefined, reject) => {reject(error)})}static race = (promiseList) => {let execute = falsereturn new XPromise((resolve, reject) => {promiseList.forEach(promiseItem => {// 每个promiseItem都是xpromise 那就可以通过.then获取值promiseItem.then(val => {if (execute) return;resolve(val)execute = true}, error => {if (execute) return;reject(error)execute = true})});})}static all = (promiseList) => {return new XPromise((resolve, reject) => {// 1. 用于存储每个promise的结果// 2. 返回的promise结果顺序与接入的promise顺序相同故使用new Array(promiseList.length);的方式存结果const result = new Array(promiseList.length);// 用于计数运行了多个个promiselet num = 0promiseList.forEach((promiseItem, index) => {// 每一个结果都是一个对象result[index] = {}promiseItem.then(val => {// 更新该位置的promise信息result[index]['status'] = "fulfilled"result[index]['value'] = val// 如果都运行完了就直接resolve// 证明所有promise都是成功的, 整个promise状态也是成功的num ++if (num >= promiseList.length) resolve(result)}, error => {// 在promise数组中有某个promise失败了// 整个promise状态算失败,reject失败最快的那个即可reject(error)})})})}static allSettled = (promiseList) => {return new XPromise((resolve, reject) => {// 1. 用于存储每个promise的结果// 2. 返回的promise结果顺序与接入的promise顺序相同故使用new Array(promiseList.length);的方式存结果const result = new Array(promiseList.length);// 用于计数运行了多个个promiselet num = 0promiseList.forEach((promiseItem, index) => {// 每一个结果都是一个对象result[index] = {};promiseItem.then((val)=> {// 更新该位置的promise信息result[index]['status'] = "fulfilled"result[index]['value'] = val// 如果都运行完了就直接resolvenum ++if (num >= promiseList.length) resolve(result)}, error => {// 更新该位置的promise信息result[index]['status'] = "rejected"result[index]['reason'] = error// 如果都运行完了就直接resolvenum ++if (num >= promiseList.length) resolve(result)})})})}static any = (promiseList) => {return new XPromise((resolve, reject) => {// 1. 用于存储每个promise的结果// 2. 返回的快的promise结果先push入数组const result = []// 用于计数运行了多个个promiselet num = 0// 等每个promise都处理完了,根据每个promise结果决定整个promise的结果const dealResult = () => {// 看能否找到一个成功的promise,先找到的也就是返回最快的promiseconst successPromise = result.find(resultItem => resultItem.status === 'fulfilled')if (successPromise) {resolve(successPromise)} else {throw new Error('All promises were rejected')}}promiseList.forEach((promiseItem, index) => {// 每一个结果都是一个对象const resultItem = {}promiseItem.then((val)=> {// 更新该位置的promise信息resultItem['status'] = "fulfilled"resultItem['value'] = valresult.push(resultItem)// 如果都运行完了再判断整个Promise的状态num ++if (num >= promiseList.length) dealResult()}, error => {// 更新该位置的promise信息resultItem['status'] = "rejected"resultItem['value'] = errorresult.push(resultItem)// 如果都运行完了再判断整个Promise的状态num ++if (num >= promiseList.length) dealResult()})})})}}export default XPromise;

代码运行效果如下:
在这里插入图片描述

参考文档

promise-catch


http://www.ppmy.cn/news/697208.html

相关文章

UE5 MetaHuman SDK插件的使用【二、聊天机器人】

目录 制作: 流程制作【相对复杂但逻辑清楚】: 快速制作【有个函数把上面的流程全部合在了一起,只需要用一个函数即可】 3个结构体的参数 combo后面的逻辑: 效果: ​编辑 代码 在前面的文章中,我们创…

华为到底有多强,让这么多国家害怕?

华为大家都知道是一家中国企业,也是一家没有上市但也不会上市的企业,但其实很多人只知道华为的手机,更多人的只知道华为很牛。还有更多的人不知道华为其实在其他领域也有很高的建树。 先说说手机方面,在手机方面华为手机2018年预计…

美国商务部宣布对华为禁令推迟90天实施

【TechWeb】5月21日消息,据国外媒体报道,美国商务部周一宣布,将对华为的禁令推迟90天实施,直到8月中旬才会生效。 华为 美国商务部称,会颁发一个临时一般许可证(Temporary General License)。该…

中国制造取得技术突破,助力华为打破美国限制

华为即将在2月24日发布新款手机,从宣传海报可以看出它将发布第二代折叠手机mateXs,而为华为提供折叠OLED面板的将是京东方。华为第二代折叠手机如期发布,显示出它并未受美国技术限制的影响,手机新品继续按计划推进,很显…

欧美的运营商都发现不能没有华为的设备,它们的计划失败了

在英国运营商表示拆除华为5G设备的计划将不得不延迟半年时间之后,美国的地方小运营商也表示FCC如果不给出56亿美元的补贴那么它们也无法以其他设备商的设备替代华为的设备,如此说明当下欧美计划以爱立信、诺基亚等设备商的设备替代华为的计划几乎破产了。…

华为:为什么美国更需要华为 而不是华为更需要美国

钛媒体注:近日,美国知名科技博客GigaOM突然发表了一篇文章《为什么美国更需要华为,而不是华为更需要美国》,文章罕见地将天平倒向了华为一方,这一美国媒体认为,如今,有能力建设一个相当好的移动…

美国服务器换成中国时间

1、使用tzselect命令修改时区(本文是以centos 7 64bit为例,centos 6.8 也适用) tzselect 选择5 Asia(亚洲) 修改centos时间,修改Linux时区,修改linux系统时区,修改linux系统时间,修改时区,国外Linux服务器修改为系统时间为国内东八区&#x…

华为手机大变?余承东被传离职转岗,进军美国受阻惹的祸?

下午,余承东离职、转岗的消息开始在微信群、朋友圈流传。 消息称:余承东下月不再担任华为终端董事长的信息开始在网络传播。据说来源于华为消息人士。 消息称“华为终端董事长余承东即将与今年3月份也就是下个月正式卸任这一职位,未来华为终端…