-
Notifications
You must be signed in to change notification settings - Fork 226
实现一个完美符合Promise/A+规范的Promise #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
请教一个问题,在v4版本中resolvePromise函数需要4个参数,为啥在then方法的实现里只传了一个promise参数呢 |
v4.0 版本中加的 setTimeout 是起什么作用的, v3.0 里没有提及 |
你好,then方法返回的也是一个promise,也是一个异步的,这里用setTimeout包裹,使得then方法被调用后,不会阻塞后续的同步任务。 |
推荐去看一下作者的源码,这块代码好像写错了。 |
第二个案例为什么会先输出一个undefined呢 原生的直接输出1 没有undefined |
prmoise === x 的时候应该reject(new TypeError()) 而不是throw吧? |
你好,问一下为什么第一个案例无法处理异步的resolve啊 |
您好,我想问一下为什么要保存this呀, const self = this; |
因为执行then的时候还没有resolve,status还是pending所以不会执行onFullfilled |
外层有try catch |
不做处理的话,会发生隐式绑定,导致this丢失问题 |
第2个案列中,为什么会先输出个undefined的 |
因为switch没有使用break的话,匹配到了会一直往下执行的,作者漏贴了吧。推荐去把源码下下来。
应该改为
|
您好! |
因为 new myPromise() 执行完同步构造函数进行实例化之后,立马又执行了同步的then方法, new myPromise((resolve, reject) => {
setTimeout(()=>{
// 过了1s执行了resolve,把状态修改成`onFulfilled`,
// 但是then已经在初始化Promise后立即执行了,then应该在执行了resolve()之后执行
resolve("end");
}, 1000);
}).then((data)=>{
// 这个匿名回调函数不会执行,因为then执行的时候,状态还是pending
console.log(data);
}) |
你好,在第二个案例中switch少了个break; |
case “pending” 那缺少个break |
文章写的代码可能有误,直接看源码里面的,那个是正确的额 |
我手写的文章里面可能有误,直接看我给的源码地址,那里面是对的 |
有个问题,执行器传入的reslove应该是能接受promise或者theable对象并且不会直接将值传入的,但是按照作者的实现,执行器里的reslove只是单纯的传值,这个不是promiseA+的标准吗。。 |
@forthealllight resolvePromise 函数使用的地方应该少传了三个参数, let temple=onFullfilled(self.value);
resolvePromise(temple) 应该是这样? let temple=onFullfilled(self.value);
resolvePromise(promise2, temple, resolve, reject) |
简要介绍:Promise允许我们通过链式调用的方式来解决“回调地狱”的问题,特别是在异步过程中,通过Promise可以保证代码的整洁性和可读性。本文主要解读Promise/A+规范,并在此规范的基础上,自己实现一个Promise.
一、Promise的使用
在了解Promise规范之前,我们知道主流的高版本浏览器已经支持ECMA中的Promise.
创建一个promise实例:
上述是一个promise的实例,输出内容为,“创建一个promise”,延迟1000ms后,输出"success"。
从上述的例子可以看出,promise方便处理异步操作。此外promise还可以链式的调用:
此外Promise除了then方法外,还提供了Promise.resolve、Promise.all、Promise.race等等方法。
二、Promise/A+规范
Promise/A+规范扩展了早期的Promise/A proposal提案,我们来解读一下Promise/A+规范。
1.术语
(1)"promise"是一个对象或者函数,该对象或者函数有一个then方法
(2)"thenable"是一个对象或者函数,用来定义then方法
(3)"value"是promise状态成功时的值
(4)"reason"是promise状态失败时的值
我们明确术语的目的,是为了在自己实现promise时,保持代码的规范性(也可以跳过此小节)
2.要求
(1)一个promise必须有3个状态,pending,fulfilled(resolved),rejected当处于pending状态的时候,可以转移到fulfilled(resolved)或者rejected状态。当处于fulfilled(resolved)状态或者rejected状态的时候,就不可变。
promise英文译为承诺,也就是说promise的状态一旦发生改变,就永远是不可逆的。
(2)一个promise必须有一个then方法,then方法接受两个参数:
其中onFulfilled方法表示状态从pending——>fulfilled(resolved)时所执行的方法,而onRejected表示状态从pending——>rejected所执行的方法。
(3)为了实现链式调用,then方法必须返回一个promise
三、实现一个符合Promise/A+规范的Promise
解读了Promise/A+规范之后,下面我们来看如何实现一个Promise,
首先构造一个myPromise函数,关于所有变量和函数名,应该与规范中保持相同。
1.v1.0 初始版本myPromise
同时,需要在myPromise的原型上定义链式调用的then方法:
上述就是一个初始版本的myPromise,在myPromise里发生状态改变,然后在相应的then方法里面根据不同的状态可以执行不同的操作。
但是这里myPromise无法处理异步的resolve.比如:
2.v2.0基于观察模式实现
为了处理异步resolve,我们修改myPromise的定义,用2个数组onFullfilledArray和onRejectedArray来保存异步的方法。在状态发生改变时,一次遍历执行数组中的方法。
对于then方法,状态为pending时,往数组里面添加方法:
这样,通过两个数组,在状态发生改变之后再开始执行,这样可以处理异步resolve无法调用的问题。这个版本的myPromise就能处理所有的异步,那么这样做就完整了吗?
没有,我们做Promise/A+规范的最大的特点就是链式调用,也就是说then方法返回的应该是一个promise。
3.v3.0then方法实现链式调用
要通过then方法实现链式调用,那么也就是说then方法每次调用需要返回一个primise,同时在返回promise的构造体里面,增加错误处理部分,我们来改造then方法
这样通过then方法返回一个promise就可以实现链式的调用:
这样我们虽然实现了then函数的链式调用,但是还有一个问题,就是在Promise/A+规范中then函数里面的onFullfilled方法和onRejected方法的返回值可以是对象,函数,甚至是另一个promise。
4.v4.0 then函数中的onFullfilled和onRejected方法的返回值问题
特别的为了解决onFullfilled和onRejected方法的返回值可能是一个promise的问题。
(1)首先来看promise中对于onFullfilled函数的返回值的要求
I)如果onFullfilled函数返回的是该promise本身,那么会抛出类型错误
II)如果onFullfilled函数返回的是一个不同的promise,那么执行该promise的then函数,在then函数里将这个promise的状态转移给新的promise
III)如果返回的是一个嵌套类型的promsie,那么需要递归。
IV)如果返回的是非promsie的对象或者函数,那么会选择直接将该对象或者函数,给新的promise。
根据上述返回值的要求,我们要重新的定义resolve函数,这里Promise/A+规范里面称为:resolvePromise函数,该函数接受当前的promise、onFullfilled函数或者onRejected函数的返回值、resolve和reject作为参数。
下面我们来看resolvePromise函数的定义:
改变了resolvePromise函数之后,我们在then方法里面的调用也变成了resolvePromise而不是promise。
这样就能处理onFullfilled各种返回值的情况。
到这里可能有点乱,我们再理一理,首先返回值有两个:
then函数的返回值——>返回一个新promise,从而实现链式调用
then函数中的onFullfilled和onRejected方法——>返回基本值或者新的promise
这两者其实是有关联的,onFullfilled方法的返回值可以决定then函数的返回值。
四、检测是否完全符合Promise/A+规范
具体用法请看promise test然后
结果为:
说明我们的实现完全符合Promise/A+规范。
完整代码的地址
https://github.com/forthealllight/promise-achieve
五、最后补充Typescript实现的Promise/A+规范(可以忽略此节)
单纯的写个工具函数,用ts还是有点影响可读性。
The text was updated successfully, but these errors were encountered: