您现在的位置是:主页 > news > 佛山制作手机网站/360网站推广怎么做

佛山制作手机网站/360网站推广怎么做

admin2025/4/27 23:00:50news

简介佛山制作手机网站,360网站推广怎么做,网站建设维护人员,做阿里巴巴网站图片介绍MyPromise MyPromise是模仿Promise实现的一套异步处理框架,但是MyPromise是使用setTimeout和ES6语法实现的。其中ES6语法是可选的。 它跟ES6标准实现的Promise是有区别的: ES6的Promise是使用micro-task-queue,回调在一轮事件循环里就可以…

佛山制作手机网站,360网站推广怎么做,网站建设维护人员,做阿里巴巴网站图片介绍MyPromise MyPromise是模仿Promise实现的一套异步处理框架,但是MyPromise是使用setTimeout和ES6语法实现的。其中ES6语法是可选的。 它跟ES6标准实现的Promise是有区别的: ES6的Promise是使用micro-task-queue,回调在一轮事件循环里就可以…

介绍MyPromise

MyPromise是模仿Promise实现的一套异步处理框架,但是MyPromise是使用setTimeout和ES6语法实现的。其中ES6语法是可选的。

它跟ES6标准实现的Promise是有区别的:

ES6的Promise是使用micro-task-queue,回调在一轮事件循环里就可以被主线程执行;

而MyPromise由于是使用setTimeout实现的,回调是放在macro-task-queue里,所以会在下一轮事件循环被主线程执行。

micro-task-queue和macro-task-queue的介绍可以看我的另一篇文章

以ES6的Promise为参考

ES6的Promise规范可以参考MDN。

MyPromise将依次实现以下API:

Promise.prototype.then()
Promise.prototype.catch()
Promise.prototype.finally()
Promise.resolve()
Promise.reject()
Promise.race()
Promise.all()
复制代码

必备的知识

  1. ES6的一些基础语法,如class
  2. Function.prototype.bind()
  3. 闭包
  4. setTimeout异步处理思维

MyPromise原理

  1. 基于setTimeout实现的异步框架;
  2. 存储每一次链式调用的回调;
  3. 在发起resolve(成功)或reject(失败)时发起异步处理。

用一张图描述整个业务逻辑:

逐个实现API

完整的代码可以看:./src/MyPromise.js

1. MyPromise的构造函数

首先需要保留MyPromise的状态,有3个状态:pending(未完成状态)、resolved(成功状态)、rejected(失败状态);

其次需要存储链式调用中的回调函数(下面称之为chain-callback),使用数组来存储它们;

最后调用构造函数传入进来的实参回调(下面称之为argument-callback)。

代码如下:

constructor(fun) {this.state = stateEnum.pendingthis.fun = funthis.onResolvedArray = [];this.onRejectedArray = [];try {this.fun.call(undefined, resolve.bind(this), reject.bind(this))} catch (err) {// 处理错误reject.bind(this)(err)}
}
复制代码

2. 对于resolve和reject函数

这两个函数才是MyPromise的灵魂所在,我并没有把它们放在构造函数或者构造函数的prototype里是因为不想它被使用者破坏。 这里使用resolve和reject命名是为了跟随潮流,别的命名也是可以的。 先把代码贴出来,由于resolve和reject函数逻辑差不多,这里仅讲解一下resolve:

const resolve = function (value) {if (this.state === stateEnum.pending) {setTimeout(() => {let result;// 过滤onResolvedArray中undefined的情况,注意避免死循环while (!(this.onResolvedArray[0] instanceof Function)) {if (!this.onResolvedArray.length) returnthis.onResolvedArray.shift()this.onRejectedArray.shift()}try {result = this.onResolvedArray[0].call(undefined, value)// 判断返回的是不是一个Promise对象if (!(result instanceof MyPromise)) {result = MyPromise.resolve()}this.state = stateEnum.resolved} catch (err) {result = MyPromise.reject(err)} finally {this.onResolvedArray.shift()this.onRejectedArray.shift()result.fillCallbacks(this.onResolvedArray, this.onRejectedArray)}})}
}
复制代码
  1. 为了防止在argument-callback多次调用resolve引起的不正常现象,我们对MyPromise对象的状态进行判断;
  2. argument-callback里调用了resolve之后,除了进行状态判断,还会向定时器线程发起一个异步调用(也就是setTimeout),让它立即把回调放入任务队列(macro-task-queue)中,等待主线程的执行;
  3. 等到主线程执行这个回调的时候,会把chain-callback中取出一个回调执行,并判断返回的结果是不是另一个MyPromise,如果不是则创造一个没有带值的MyPromise,并把chain-callback的剩下回调传给新的MyPromise;
  4. 继续等待MyPromise里的argument-callback调用resolve方法,回到2。

这就是链式调用的关键逻辑

3. then、catch、finally

这三个函数都是为了填充MyPromise对象的chain-callback,逻辑很简单。

then() {this.onResolvedArray.push(arguments[0])this.onRejectedArray.push(arguments[1])return this
}
catch () {this.onResolvedArray.push(undefined)this.onRejectedArray.push(arguments[0])return this
}
finally() {this.onResolvedArray.push(arguments[0])this.onRejectedArray.push(arguments[0])return this
}
复制代码

4. MyPromise.resolve和MyPromise.reject

这两个方法不同于前面介绍的resolve和reject,它们是MyPromise类上的方法,主要作用是创建一个MyPromise对象并调用argument-callback里的resolve或reject:

static resolve(value) {if (value instanceof MyPromise) return valuereturn new MyPromise((_resolve, _reject) => {_resolve(value)})
}static reject(err) {return new MyPromise((_resolve, _reject) => {_reject(err)})
}
复制代码

5. MyPromise.race和MyPromise.all

到这里,其实已经介绍完MyPromise的主要代码和逻辑。

而MyPromise.race和MyPromise.all提供了一些特殊的用途,借用MDN的介绍。

Promise.race(iterable) 方法返回一个 promise ,并伴随着 promise对象解决的返回值或拒绝的错误原因, 只要 iterable 中有一个 promise 对象"解决(resolve)"或"拒绝(reject)"。

static race(arr) {const paramsArr = Array.prototype.slice.call(arr)return new MyPromise((resolve, reject) => {paramsArr.map((item, index, arr) => {if (!(item instanceof MyPromise)) {item = MyPromise.resolve(item)}item.then(val => {resolve(val)}, err => {reject(err)})})})
}
复制代码

Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(rejecte),失败原因的是第一个失败 promise 的结果。

static all(arr) {const results = []const paramsArr = Array.prototype.slice.call(arr)let numOfPromise = 0return new MyPromise((resolve, reject) => {paramsArr.map((value, index, arr) => {if (value instanceof MyPromise) {++numOfPromise;value.then(val => {results[index] = val;--numOfPromise;if (numOfPromise === 0) {resolve(results)}}, err => {reject(err)})} else {results[index] = value}})})
}
复制代码

测试

上面主要介绍了resolve,而reject只是只言片语带过。希望源码和测试代码能解答你心中的疑惑。

测试代码使用了Jest框架

写在最后

如果文章哪里写的不对,还望不吝指教。

若有疑问,可以在issue中给我留言。

谢谢你能看到这里。