You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
2.2.5. onFulfilled and onRejected must be called as functions (i.e. with no this value). (strict mode 下,this = undefined,而在平常模式下,this 指向 global object)
2.2.6. then 方法也许会在同一个 promise 中被调用多次
2.2.7. then must return a promise
promise2 =promise1.then(onFulfilled, onRejected);
If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure[[Resolve]](promise2, x).
If either onFulfilled or onRejected throws an exception e, promise2 must be rejected with e as the reason.
If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled with the same value as promise1.
If onRejected is not a function and promise1 is rejected, promise2 must be rejected with the same reason as promise1.
try{module.exports=Promise}catch(e){}functionPromise(executor){varself=thisself.status='pending'self.onResolvedCallback=[]self.onRejectedCallback=[]functionresolve(value){if(valueinstanceofPromise){returnvalue.then(resolve,reject)}setTimeout(function(){// 异步执行所有的回调函数if(self.status==='pending'){self.status='resolved'self.data=valuefor(vari=0;i<self.onResolvedCallback.length;i++){self.onResolvedCallback[i](value)}}})}functionreject(reason){setTimeout(function(){// 异步执行所有的回调函数if(self.status==='pending'){self.status='rejected'self.data=reasonfor(vari=0;i<self.onRejectedCallback.length;i++){self.onRejectedCallback[i](reason)}}})}try{executor(resolve,reject)}catch(reason){reject(reason)}}/*resolvePromise函数即为根据x的值来决定promise2的状态的函数也即标准中的[Promise Resolution Procedure](https://promisesaplus.com/#point-47)x为`promise2 = promise1.then(onResolved, onRejected)`里`onResolved/onRejected`的返回值`resolve`和`reject`实际上是`promise2`的`executor`的两个实参,因为很难挂在其它的地方,所以一并传进来。相信各位一定可以对照标准把标准转换成代码,这里就只标出代码在标准中对应的位置,只在必要的地方做一些解释*/functionresolvePromise(promise2,x,resolve,reject){varthenvarthenCalledOrThrow=falseif(promise2===x){returnreject(newTypeError('Chaining cycle detected for promise!'))}if(xinstanceofPromise){if(x.status==='pending'){//because x could resolved by a Promise Objectx.then(function(v){resolvePromise(promise2,v,resolve,reject)},reject)}else{//but if it is resolved, it will never resolved by a Promise Object but a static value;x.then(resolve,reject)}return}if((x!==null)&&((typeofx==='object')||(typeofx==='function'))){try{then=x.then//because x.then could be a getterif(typeofthen==='function'){then.call(x,functionrs(y){if(thenCalledOrThrow)returnthenCalledOrThrow=truereturnresolvePromise(promise2,y,resolve,reject)},functionrj(r){if(thenCalledOrThrow)returnthenCalledOrThrow=truereturnreject(r)})}else{resolve(x)}}catch(e){if(thenCalledOrThrow)returnthenCalledOrThrow=truereturnreject(e)}}else{resolve(x)}}Promise.prototype.then=function(onResolved,onRejected){varself=thisvarpromise2onResolved=typeofonResolved==='function' ? onResolved : function(v){returnv}onRejected=typeofonRejected==='function' ? onRejected : function(r){throwr}if(self.status==='resolved'){returnpromise2=newPromise(function(resolve,reject){setTimeout(function(){// 异步执行onResolvedtry{varx=onResolved(self.data)resolvePromise(promise2,x,resolve,reject)}catch(reason){reject(reason)}})})}if(self.status==='rejected'){returnpromise2=newPromise(function(resolve,reject){setTimeout(function(){// 异步执行onRejectedtry{varx=onRejected(self.data)resolvePromise(promise2,x,resolve,reject)}catch(reason){reject(reason)}})})}if(self.status==='pending'){// 这里之所以没有异步执行,是因为这些函数必然会被resolve或reject调用,而resolve或reject函数里的内容已是异步执行,构造函数里的定义returnpromise2=newPromise(function(resolve,reject){self.onResolvedCallback.push(function(value){try{varx=onResolved(value)resolvePromise(promise2,x,resolve,reject)}catch(r){reject(r)}})self.onRejectedCallback.push(function(reason){try{varx=onRejected(reason)resolvePromise(promise2,x,resolve,reject)}catch(r){reject(r)}})})}}Promise.prototype.catch=function(onRejected){returnthis.then(null,onRejected)}Promise.deferred=Promise.defer=function(){vardfd={}dfd.promise=newPromise(function(resolve,reject){dfd.resolve=resolvedfd.reject=reject})returndfd}
JavaScript 之 Promise / A+ 规范
[Promises/A+](https://promisesaplus.com/)
Promise / A+ 规范是一个开放的标准,它详细描述了
Promise
对象的行为,以确保不同的实现可以互相兼容。之所以需要 Promise A+ 规范,主要是因为以下原因:Promise
库都能够无缝地工作在一起,这对于开发大型、模块化的应用程序来说非常重要。then
方法的行为,包括值的传播和错误的处理。这消除了开发者的猜测,并减少了代码中的错误。总的来说,Promise A+ 规范的存在极大地改善了JavaScript编程环境,使得异步编程更加可靠、一致和可预测。它帮助确立了一个行业标准,让开发者可以放心地使用
Promise
,并确信它们会按照预期的方式工作。1. Terminology
promise
- is an object or function with athen
method whose behavior conforms to this specification.thenable
- is an object or function that defines athen
method.value
- is any legal JavaScript value (includingundefined
, a thenable, or a promise).exception
- is a value that is thrown using thethrow
statement.reason
- is a value that indicates why a promise was rejected.2. Requirements
2.1 Promise States
promise 的当前状态必须为以下三种状态之一:
Pending
,Fulfilled
,Rejected
2.2 The
then
Methodthen
method accepts two arguments:promise.then(onFulfilled, onRejected)
2.2.1. onFulfilled, onRejected 都为可选参数,如果输入并非一个 Function,则 ignore
2.2.2. onFulfilled 必须等到 promise fulfilled 后再运行,并且以 promise‘s value 作为第一个参数
2.2.3. onRejected 必须等到 promise rejected 后再运行,并且以 promise’s reason 作为第一个参数
2.2.4.
onFulfilled
oronRejected
must not be called until the [execution context](https://es5.github.io/#x10.3) stack contains only platform code.setTimeout
/setImmediate
在下一次 macrotask 中执行。或者使用MutationObserver
/process.nextTick
在本次事件循环的 microtask 中执行。2.2.5.
onFulfilled
andonRejected
must be called as functions (i.e. with nothis
value). (strict mode 下,this = undefined,而在平常模式下,this 指向 global object)2.2.6.
then
方法也许会在同一个 promise 中被调用多次2.2.7.
then
must return a promiseonFulfilled
oronRejected
returns a valuex
, run the Promise Resolution Procedure[[Resolve]](promise2, x)
.onFulfilled
oronRejected
throws an exceptione
,promise2
must be rejected withe
as the reason.onFulfilled
is not a function andpromise1
is fulfilled,promise2
must be fulfilled with the same value aspromise1
.onRejected
is not a function andpromise1
is rejected,promise2
must be rejected with the same reason aspromise1
.(在这里 3 和 4 描述的其实就是结果透传,无论 promise1 fulfilled 或者 rejected 了,如果 promise2 没法消费这个信息的话,就会把结果传递给下一个 promise)
2.2.7.3 举个例子
此时由于 promise1.then() 的第一个参数不是 function,因此 promise2 接收到了 promise1 resolve 得到的值,打印出
promise2: Promise 1 resolved
(resolve 的值被透传了,直到被消费为止)
此时 promise1 的 resolve 的值被自己的 then 函数的第一个参数函数给消费掉了,最终的打印结果是
promise1: Promise 1 resolved
promise2: undefined
如果在代码
Here~~~
处 return 一些值,则可以成功传递给 promsie22.3 The Promise Resolution Procedure
The promise resolution procedure is an abstract operation taking as input a promise and a value, which we denote as
[[Resolve]](promise, x)
.如果 x 是一个 thenable 的对象,那么使 promise 采用 x 此时的状态并且执行
如果 x 不是一个 thenable 的对象,那么 promise 使用 x 作为 value 来完成自己的 promise 流程
例如这个例子中,标红的地方 return 后续的就是 x
如果说 x 是
return 123;
那么在 ES6 中会自动的进行
Promise.resolve(123)
以 123 作为值返回一个状态为 resolved 的 Promise 对象此时就会打印出
promise2: 123
如果说 x 是
return new Promise(…)
那么就会根据 x 的状态来决定 promise2 的状态
To run
[[Resolve]](promise, x)
, perform the following steps:2.3.1. 如果 promise 和 x 指向同一个 object,reject promise with a TypeError
注意,
promise2 = promise1.then(onFulfilled, onRejected)
; 会执行[[Resolve]](promise2, x)
也就是说,当我们在函数里面 return promise2, 就会报错TypeError: Chaining cycle detected for promise #<Promise>
2.3.2 如果 x 是一个 promise,则采用它的状态
2.3.2.1 如果 x 是 pending 中,等待 x pending 结束
2.3.2.2 如果 x 是 fulfilled,fulfill promise with same value (也就是说我们此时 resolve(val) 外 promise2 也会使用 val 进行自己的 resolve)
2.3.2.3 如果 x 是 rejected,fulfill promise with same err
2.3.3 如果 x 是一个对象或者函数
2.3.3.1 如果 x 中包含 then 方法那么就执行这个 then 方法,call it with
x
asthis
, first argumentresolvePromise
, and second argumentrejectPromise
resolvePromise
called with a value y → run[[Resolve]](promise, y)
. 因此会有一个迭代解析发生rejectPromise
called with a reason err → reject promise with errresolvePromise
和rejectPromise
都被调用了或者被调用了多次,那么只管第一个出现的,后续出现的不要管!resolvePromise
或者rejectPromise
,那么忽视这个 err。否则的话,reject promise with err as the reason2.3.3.2 如果 x 就是一个纯纯的对象或者函数,而没有 then,或者 then 不是一个 function。那么就 fulfill promise with x
2.3.4 如果 x 不是一个对象或者函数
fulfill
promise
withx
.实现 Promise
xieranmaya/blog#3
调用
基本框架
注意这个地方
onResolvedCallback
怎么样才能往这个数组里面 push function 呢?通过
then
方法,但是有一个细节需要注意!例如这里的方式,就成功往这个数组里面push了回调函数。并且会连续打印两个
111
也就是说,同一个 value 会被用于
onResolvedCallback
里面的所有函数然而这种方式只往数组里面push了一个 callback function。并且打印结果是
111
和undefined
。 这是因为then
方法返回的是一个新的 promise,因此第二个 then 方法实际上是 push 到了这个新的 promise 的 onResolvedCallback 中。考虑
resolve
和reject
then
方法var x = onResolved(self.data)
这一部分后续的内容可以结合前面提到的 Promise Resolve Procedure 规范思考一些其它问题
Promise 穿透
希望 alert(8)
我们只需要把then里判断
onResolved
和onRejected
的部分改成如下即可:完整代码
最简实现Promise,支持异步链式调用(20行)
[最简实现Promise,支持异步链式调用(20行) - 掘金](https://juejin.cn/post/6844904094079926286)
一道有趣的面试题
最后这里再贡献一道有趣的面试题,最终输出的结果竟然是
0 1 2 3 4 5 6
关键问题在于
return Promise.resolve(4)
,这句话实际上包含一个非常复杂的流程首先,Promise 内部会试图解析 return x 的这个 x(这里 x 是
Promise.resolve(4)
),这一步是一个微任务然后,Promise 解析成功后要执行
Promise.resolve(4)
,这一步也是一个微任务随后才是执行
.then(res => console.log(res))
因此整段下来,微任务队列入队情况类似于
也可以理解成
The text was updated successfully, but these errors were encountered: