Promises A+規(guī)范原文解讀 + es6實(shí)現(xiàn)(附詳細(xì)注釋)

英文官方文檔原文:https://promisesaplus.com/

前言

寫本文的目的,是為了更好的理解promise狡相,通過解讀翻譯原文茶袒,逐行解析原文通過代碼一行一行實(shí)現(xiàn)溯壶。希望通過這篇文章,讓我們能對promise有更深入的了解圃郊。

首先介紹promises是什么价涝,英文的字面意思是“承諾”的意思,接下來promises翻譯我沒有用承諾翻譯這個(gè)單詞持舆,因?yàn)槲矣X得有些英文只是一個(gè)詞匯色瘩,還是直接用英文原文叫法好伪窖。

promise的是解決回調(diào)的問題的,通過then的鏈?zhǔn)秸{(diào)用居兆,讓我們能更清晰的理解閱讀代碼覆山。下面直接看原文解讀:

英: An open standard for sound, interoperable JavaScript promises—by implementers, for implementers.

中: 一個(gè)開源標(biāo)準(zhǔn),可與JS互操作的Promises泥栖。由 implementers(語意創(chuàng)作這個(gè)promises的人或團(tuán)體)創(chuàng)作簇宽,implementers(實(shí)現(xiàn)者)。

英: A promise represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its then method, which registers callbacks to receive either a promise’s eventual value or the reason why the promise cannot be fulfilled.

中: 一個(gè)promise代表了異步操作的最終結(jié)果吧享。與一個(gè)promise完成交互的主要方法是then方法魏割,該方法會(huì)記錄回調(diào)以接收一個(gè)promise的成功返回值或者失敗的原因。

英: This specification details the behavior of the then method, providing an interoperable base which all Promises/A+ conformant promise implementations can be depended on to provide. As such, the specification should be considered very stable. Although the Promises/A+ organization may occasionally revise this specification with minor backward-compatible changes to address newly-discovered corner cases, we will integrate large or backward-incompatible changes only after careful consideration, discussion, and testing.

中: 本規(guī)范詳細(xì)的描述了then方法的行為钢颂,提供了一個(gè)可互操作的基礎(chǔ)钞它,所有的Promises / A +符合promise實(shí)現(xiàn)都可依賴提供。因此甸陌,本規(guī)范應(yīng)該被認(rèn)為是非常穩(wěn)定的须揣。雖然Promises / A +組織偶爾會(huì)修改這個(gè)規(guī)范,但向后兼容更改次數(shù)較少钱豁,主要解決新發(fā)現(xiàn)的案例,我們只有在仔細(xì)考慮疯汁,討論以及測試之后才會(huì)整合大的改動(dòng)或者向后兼容的更改牲尺。

英: Historically, Promises/A+ clarifies the behavioral clauses of the earlier Promises/A proposal, extending it to cover de facto behaviors and omitting parts that are underspecified or problematic.

中: 歷史上,Promises / A +闡明了先前Promises / A提案的行為條款幌蚊,將其擴(kuò)展為涵蓋事實(shí)上的行為谤碳,并略去了未指定或存在問題的部分。

英: Finally, the core Promises/A+ specification does not deal with how to create, fulfill, or reject promises, choosing instead to focus on providing an interoperable then method. Future work in companion specifications may touch on these subjects.

中: 最后溢豆,核心Promises / A+規(guī)范不涉及如何創(chuàng)建蜒简,履行或拒絕promises,而是選擇專注于提供可互操作的方法漩仙。未來的配套規(guī)范工作可能涉及這些主題搓茬。

英: 1.Terminology

中: 1、術(shù)語

英: 1.1 “promise” is an object or function with a then method whose behavior conforms to this specification.

中: 1.1 “promise”是一個(gè)對象或函數(shù)队他,它的行為符合這個(gè)規(guī)范卷仑。

英: 1.2 “thenable” is an object or function that defines a then method.

中: 1.2 “thenable”是定義then方法的對象或函數(shù)。

英: 1.3 “value” is any legal JavaScript value (including undefined, a thenable, or a promise).

中: 1.3 “value”是任何合法的JavaScript值(包括undefined麸折,thenable或promise)锡凝。

英: 1.4 “exception” is a value that is thrown using the throw statement.

中: 1.4 “異常”是使用throw語句拋出的值垢啼。

英: 1.5 “reason” is a value that indicates why a promise was rejected.

中: 1.5 “原因”是一個(gè)值(結(jié)果)表明promise被拒絕的原因窜锯。

英: 2.Requirements

2.1.Promise States

中: 2张肾、要求

2.1.Promise狀態(tài)

英: A promise must be in one of three states: pending, fulfilled, or rejected.

中: 一個(gè)promise必須包含初始態(tài), 成功(完成)態(tài), 或者失敗(拒絕)態(tài)這三個(gè)狀態(tài)中的一種锚扎。

英: 2.1.1 When pending, a promise:<br />
2.1.1.1 may transition to either the fulfilled or rejected state.

中: 2.1.1 當(dāng)狀態(tài)是初始態(tài), promise:<br />
2.1.1.1 可能轉(zhuǎn)換到成功態(tài)或失敗態(tài)捌浩。

英: 2.1.2. When fulfilled, a promise:<br />
2.1.2.1. must not transition to any other state.<br />
2.1.2.2. must have a value, which must not change.

中: 2.1.2 當(dāng)狀態(tài)是成功態(tài),promise:<br />
2.1.2.1 不能更改成別的狀態(tài)工秩。<br />
2.1.2.2 必須有個(gè)不能更改的值(結(jié)果)

英: 2.1.3. When rejected, a promise:<br />
2.1.3.1.must not transition to any other state.<br />
2.1.3.2. must have a reason, which must not change.

中: 2.1.3 當(dāng)狀態(tài)是失敗態(tài)尸饺,promise:<br />
2.1.3.1. 不能更改成別的狀態(tài)。<br />
2.1.3.2. 必須有個(gè)不能更改的失斨摇(錯(cuò)誤)原因

英: Here, “must not change” means immutable identity (i.e. ===), but does not imply deep immutability.

中: 上面,“不能改變”的意思是不可改變的狀態(tài)(即 ===)浪听,但并不意味著深不可變。

英: 2.2.The then Method<br />
A promise must provide a then method to access its current or eventual value or reason.<br />
A promise’s then method accepts two arguments:<br />
promise.then(onFulfilled, onRejected)

中: 2.2 then方法<br />
一個(gè)promise必須有一個(gè)then方法來獲取成功的值(結(jié)果)或失斆剂狻(錯(cuò)誤)的原因迹栓。<br />
一個(gè)promise方法接收兩個(gè)參數(shù):<br />
promise.then(onFulfilled, onRejected)

英: 2.2.1. Both onFulfilled and onRejected are optional arguments:<br />
2.2.1.1.If onFulfilled is not a function, it must be ignored.<br />
2.2.1.2.If onRejected is not a function, it must be ignored.

中: 2.2.1. onFulfilled和onRejected都是可選參數(shù):<br />
2.2.1.1 如果onFulfilled不是函數(shù),則必須忽略它俭缓。<br />
2.2.1.2 如果onRejected不是函數(shù)克伊,則必須忽略它。

英: 2.2.2 If onFulfilled is a function:<br />
2.2.2.1.it must be called after promise is fulfilled, with promise’s value as its first argument.<br />
2.2.2.2.it must not be called before promise is fulfilled.<br />
2.2.2.3.it must not be called more than once.

中: 2.2.2 如果onFulfilled是一個(gè)函數(shù):<br />
2.2.2.1 必須在promise執(zhí)行完成后調(diào)用华坦,promise的返回值作為第一個(gè)參數(shù)愿吹。<br />
2.2.2.2 在promise執(zhí)行前不得調(diào)用。<br />
2.2.2.3 只能調(diào)用一次惜姐。

英: 2.2.3.If onRejected is a function,<br />
2.2.3.1.it must be called after promise is rejected, with promise’s reason as its first argument.<br />
2.2.3.2.it must not be called before promise is rejected.<br />
2.2.3.3.it must not be called more than once.

中: 2.2.3 如果onRejected是一個(gè)函數(shù):<br />
2.2.3.1 必須在promise執(zhí)行完成后調(diào)用犁跪,promise的錯(cuò)誤原因作為第一個(gè)參數(shù)。<br />
2.2.3.2 在promise執(zhí)行前不得調(diào)用歹袁。<br />
2.2.3.3 只能調(diào)用一次坷衍。

英: 2.2.4.onFulfilled or onRejected must not be called until the execution context stack contains only platform code. [3.1].

中: 2.2.4 在執(zhí)行上下文堆棧僅包含平臺(tái)代碼之前,不能調(diào)用onFulfilled或onRejected条舔。[3.1]枫耳。

英: 2.2.5 onFulfilled and onRejected must be called as functions (i.e. with no this value). [3.2]

中: onFulfilled和onRejected必須是函數(shù)(即 沒有這個(gè)值)。[3.2]

英: 2.2.6.then may be called multiple times on the same promise.<br />
2.2.6.1.If/when promise is fulfilled, all respective onFulfilled callbacks must execute in the order of their originating calls to then.<br />
2.2.6.2.If/when promise is rejected, all respective onRejected callbacks must execute in the order of their originating calls to then.

中: 2.2.6 then方法可能會(huì)在相同的promise被多次調(diào)用孟抗。<br />
2.2.6.1 如果/當(dāng)promise成功時(shí)迁杨,所有各自的onFulfilled回調(diào)必須按照其始發(fā)調(diào)用的順序執(zhí)行。<br />
2.2.6.2 如果/當(dāng)promise失敗時(shí)夸浅,所有各自的onRejected回調(diào)必須按照其始發(fā)調(diào)用的順序執(zhí)行仑最。<br />

英: 2.2.7. then must return a promise [3.3].<br />
promise2 = promise1.then(onFulfilled, onRejected);<br />
2.2.7.1.If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x).<br />
2.2.7.2.If either onFulfilled or onRejected throws an exception e, promise2 must be rejected with e as the reason.<br />
2.2.7.3.If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled with the same value as promise1.<br />
2.2.7.4.If onRejected is not a function and promise1 is rejected, promise2 must be rejected with the same reason as promise1.

中: 2.2.7 then方法必須返回一個(gè)promise。[3.3]<br />
例如:promise2 = promise1.then(onFulfilled, onRejected);<br />
2.2.7.1 如果onFulfilled或onRejected返回一個(gè)值(結(jié)果)x帆喇,運(yùn)行Promise的解決程序 [[Resolve]](promise2警医,x)。<br />
2.2.7.2 如果onFulfilled或onRejected引發(fā)異常e,promise2必須以e作為拒絕原因预皇。<br />
2.2.7.3 如果onFulfilled不是一個(gè)函數(shù)并且promise1是被成功侈玄,那么promise2必須用與promise1相同的值執(zhí)行。<br />
2.2.7.4 如果onRejected不是函數(shù)并且promise1是被失敗吟温,那么promise2必須用與promise1相同的失敗原因序仙。

英: 2.3.The Promise Resolution Procedure

中: 2.3 Promise的解決程序

英: The promise resolution procedure is an abstract operation taking as input a promise and a value, which we denote as [[Resolve]](promise, x). If x is a thenable, it attempts to make promise adopt the state of x, under the assumption that x behaves at least somewhat like a promise. Otherwise, it fulfills promise with the value x.

中: Promise的解決程序是一個(gè)抽象操作,取得輸入的promise和一個(gè)值(結(jié)果)鲁豪,我們表示為 [[Resolve]](promise, x)潘悼。
[[Resolve]](promise, x)的意思是創(chuàng)建一個(gè)方法Resolve方法執(zhí)行時(shí)傳入兩個(gè)參數(shù)promise和x(promise成功態(tài)時(shí)返回的值)。如果x是一個(gè)thenable(見上文術(shù)語1.2)爬橡,它試圖創(chuàng)造一個(gè)promise采用x的狀態(tài)治唤,假設(shè)x的行為至少貌似promise。否則糙申,它用x值執(zhí)行promise宾添。

英: This treatment of thenables allows promise implementations to interoperate, as long as they expose a Promises/A+-compliant then method. It also allows Promises/A+ implementations to “assimilate” nonconformant implementations with reasonable then methods.

中: 對thenable的這種處理允許promise實(shí)現(xiàn)交互操作,只要它們暴露Promise / A +兼容的方法即可柜裸。 它還允許Promises / A +實(shí)現(xiàn)通過合理的方法“吸收”不合格的實(shí)現(xiàn)缕陕。

英: To run [[Resolve]](promise, x), perform the following steps:<br />
2.3.1. if promise and x refer to the same object, reject promise with a TypeError as the reason.

中: 去運(yùn)行 [[Resolve]](promise, x),需執(zhí)行以下步驟:<br />
2.3.1 如果promise和x引用同一個(gè)對象疙挺,則以TypeError為原因拒絕promise扛邑。

英: 2.3.2. If x is a promise, adopt its state [3.4]:<br />
2.3.2.1.If x is pending, promise must remain pending until x is fulfilled or rejected.<br />
2.3.2.2.If/when x is fulfilled, fulfill promise with the same value.<br />
2.3.2.3.If/when x is rejected, reject promise with the same reason.

中: 2.3.2 如果x是一個(gè)promise,采用它的狀態(tài)【3.4】:<br />
2.3.2.1 如果x是初始態(tài)衔统,promise必須保持初始態(tài)(即遞歸執(zhí)行這個(gè)解決程序)鹿榜,直到x被成功或被失敗。(即锦爵,直到resolve或者reject執(zhí)行)<br />
2.3.2.2 如果/當(dāng)x被成功時(shí),用相同的值(結(jié)果)履行promise奥裸。<br />
2.3.2.3 如果/當(dāng)x被失敗時(shí)险掀,用相同的錯(cuò)誤原因履行promise。

英: 2.3.3.Otherwise, if x is an object or function,<br />
2.3.3.1.Let then be x.then. [3.5]<br />
2.3.3.2.If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason.<br />
2.3.3.3.If then is a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise, where:<br />
2.3.3.3.1.If/when resolvePromise is called with a value y, run [[Resolve]](promise, y).<br />
2.3.3.3.2.If/when rejectPromise is called with a reason r, reject promise with r.<br />
2.3.3.3.3.If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.<br />
2.3.3.3.4.If calling then throws an exception e,<br />
2.3.3.3.4.1.If resolvePromise or rejectPromise have been called, ignore it.<br />
2.3.3.3.4.2.Otherwise, reject promise with e as the reason.<br />
2.3.3.4.If then is not a function, fulfill promise with x.

中: 2.3.3 否則湾宙,如果x是一個(gè)對象或函數(shù),<br />
2.3.3.1 讓then等于x.then樟氢。【3.5】<br />
2.3.3.2 如果x.then導(dǎo)致拋出異常e侠鳄,拒絕promise并用e作為失敗原因埠啃。<br />
2.3.3.3 如果then是一個(gè)函數(shù),則使用x作為此參數(shù)調(diào)用它伟恶,第一個(gè)參數(shù)resolvePromise碴开,第二個(gè)參數(shù)rejectPromise,其中:<br />
2.3.3.3.1 如果使用值(結(jié)果)y調(diào)用resolvePromise,運(yùn)行[[Resolve]](promise潦牛,y)我的解決程序的名字是resolveExecutor眶掌。<br />
2.3.3.3.2 如果使用拒絕原因r調(diào)用resolvePromise,運(yùn)行reject(r)巴碗。<br />
2.3.3.3.3 如果resolvePromise和rejectPromise都被調(diào)用朴爬,或者對同一個(gè)參數(shù)進(jìn)行多次調(diào)用,則第一次調(diào)用優(yōu)先橡淆,并且任何進(jìn)一步的調(diào)用都會(huì)被忽略召噩。<br />
2.3.3.3.4 如果調(diào)用then方法拋出異常e,<br />
2.3.3.3.4.1 如果resolvePromise或rejectPromise已經(jīng)調(diào)用了逸爵,則忽略它具滴。<br />
2.3.3.3.4.2 否則,以e作為失敗原因拒絕promise痊银。<br />
2.3.3.4 如果then不是一個(gè)對象或者函數(shù)抵蚊,則用x作為值(結(jié)果)履行promise。

英: 2.3.4.If x is not an object or function, fulfill promise with x.<br />
If a promise is resolved with a thenable that participates in a circular thenable chain, such that the recursive nature of [[Resolve]](promise, thenable) eventually causes [[Resolve]](promise, thenable) to be called again, following the above algorithm will lead to infinite recursion. Implementations are encouraged, but not required, to detect such recursion and reject promise with an informative TypeError as the reason. [3.6]

中: 2.3.4 如果x不是一個(gè)對象或函數(shù)溯革,則用x作為值履行promise贞绳。<br />
如果一個(gè)primse是通過一個(gè)thenable參與一個(gè)循環(huán)的可鏈接表達(dá)式來解決的thenable鏈,那么[[Resolve]](promise致稀,thenable)的遞歸性質(zhì)最終會(huì)導(dǎo)致[[Resolve]](promise冈闭,thenable)被再次調(diào)用, 上述算法將導(dǎo)致無限遞歸抖单。 支持這種實(shí)現(xiàn)萎攒,但不是必需的,來檢測這種遞歸并以一個(gè)信息性的TypeError為理由拒絕promise矛绘∷P荩【3.6】

英: 3.Notes<br />

    3.1.Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such as setTimeout or setImmediate, or with a “micro-task” mechanism such as MutationObserver or process.nextTick. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called.

中: 3.注釋<br />

    3.1 這里的“平臺(tái)代碼”是指引擎,環(huán)境和primise實(shí)現(xiàn)代碼货矮。在實(shí)踐中羊精,這個(gè)要求確保onFulfilled和onRejected異步執(zhí)行,在事件循環(huán)開始之后then被調(diào)用囚玫,和一個(gè)新的堆棧喧锦。這可以使用諸如setTimeout或setImmediate之類的“宏任務(wù)”機(jī)制,或者使用諸如MutationObserver或process.nextTick的“微任務(wù)”機(jī)制來實(shí)現(xiàn)抓督。由于promise實(shí)現(xiàn)被認(rèn)為是經(jīng)過深思熟慮的平臺(tái)代碼燃少,因此它本身可能包含調(diào)用處理程序的任務(wù)調(diào)度隊(duì)列或或稱為“trampoline”(可重用的)的處理程序。

英: 3.2.That is, in strict mode this will be undefined inside of them; in sloppy mode, it will be the global object.

中: 3.2 即:在嚴(yán)格模式下是undefined铃在;非嚴(yán)格模式下是全局對象阵具。

英: 3.3.Implementations may allow promise2 === promise1, provided the implementation meets all requirements. Each implementation should document whether it can produce promise2 === promise1 and under what conditions.

中: 3.3 實(shí)現(xiàn)可能會(huì)允許promise2 === promise1, 前提是實(shí)現(xiàn)符合所有的要求。每個(gè)實(shí)現(xiàn)應(yīng)該記錄它是否可以產(chǎn)生promise2 === promise1以及在什么條件下。

英: 3.4.Generally, it will only be known that x is a true promise if it comes from the current implementation. This clause allows the use of implementation-specific means to adopt the state of known-conformant promises.

中: 3.4 通常怔昨,只有當(dāng)它是來自當(dāng)前的實(shí)現(xiàn)時(shí)才會(huì)知道x是一個(gè)真正的promise雀久。該條款允許使用具體實(shí)現(xiàn)方法來采用已知符合性promise的狀態(tài)。

英: 3.5.This procedure of first storing a reference to x.then, then testing that reference, and then calling that reference, avoids multiple accesses to the x.then property. Such precautions are important for ensuring consistency in the face of an accessor property, whose value could change between retrievals.

中: 3.5 首先存儲(chǔ)對x.then的引用趁舀,然后測試和調(diào)用該引用赖捌,避免多次使用x.then屬性。這樣的注意事項(xiàng)對于確保訪問器的屬的一致性性非常重要矮烹,其值(結(jié)果)可能在取回時(shí)改變越庇。

英: 3.6.Implementations should not set arbitrary limits on the depth of thenable chains, and assume that beyond that arbitrary limit the recursion will be infinite. Only true cycles should lead to a TypeError; if an infinite chain of distinct thenables is encountered, recursing forever is the correct behavior.

中: 3.6 實(shí)現(xiàn)不應(yīng)該對thenable鏈做任意設(shè)定限制,假定超出該任意設(shè)定限制遞歸將是無限的奉狈。只有真正的循環(huán)才導(dǎo)致TypeError; 如果遇到不同的thenables的無限鏈卤唉,一直遞歸是正確的行為。

英: To the extent possible under law, the Promises/A+ organization has waived all copyright and related or neighboring rights to Promises/A+ Promise Specification. This work is published from: United States.

中: 在法律允許的范圍內(nèi)仁期,Promises / A +組織已放棄所有版權(quán)及Promises / A +規(guī)范的相關(guān)或相鄰權(quán)利桑驱。本作品發(fā)表于:美國。

---------以上是原文翻譯

啥也別說上代碼

class MyPromise {
  constructor(executor) {
    //緩存this
    ;let self = this
    //設(shè)置初始態(tài)
    ;self.status = 'pending'
    //定義成功的值默認(rèn)undefined
    ;self.value = undefined
    //定義失敗的原因默認(rèn)undefined
    ;self.reason = undefined
    //定義成功的回調(diào)數(shù)組
    ;self.onResolvedCallbacks = []
    //定義失敗的回調(diào)數(shù)組
    ;self.onRejectedCallbacks = []
    //定義成功時(shí)執(zhí)行的函數(shù)
    ;let resolve = value => {
      ;if (value instanceof MyPromise) return value.then(resolve, reject)
      //異步執(zhí)行成功回調(diào)
      ;setTimeout(() => {
        if (self.status === 'pending') {
          //把狀態(tài)改為成功態(tài)
          ;self.status = 'fulfilled'
          //保存成功的值
          ;self.value = value
          //遍歷執(zhí)行每個(gè)成功的回調(diào)
          ;self.onResolvedCallbacks.forEach(onFulfilled => onFulfilled(value))
        }
      })
    }
    //定義失敗時(shí)執(zhí)行的函數(shù)
    ;let reject = reason => {
      //異步執(zhí)行失敗回調(diào)
      setTimeout(() => {
        if (self.status === 'pending') {
          //把狀態(tài)改為失敗態(tài)
          ;self.status = 'rejected'
          //保存失敗的原因
          ;self.reason = reason
          //遍歷執(zhí)行每個(gè)失敗的回調(diào)
          ;self.onRejectedCallbacks.forEach(onRejected => onRejected(reason))
        }
      })
    }
    //由于調(diào)用executor這個(gè)方法有可能異常跛蛋,需要將捕獲的異常reject出去
    ;try {
      //運(yùn)行傳進(jìn)來的函數(shù)把成功和失敗的方法傳進(jìn)去
      ;executor(resolve, reject)
    } catch (e) {
      ;reject(e)
    }
  }
  /**
   * @param {value} onFulfilled //值的穿透熬的,默認(rèn)值往后傳
   * @param {reason} onRejected //默認(rèn)把失敗原因往后拋
   */
  then(onFulfilled = value => value, onRejected = reason => {throw reason}) {
    //緩存this,定義promise2
    ;let self = this
    ;let promise2
    //promise主要解決程序,也是promise的難點(diǎn)
    ;let resolveExecutor = (promise2, x, resolve, reject) => {
      // 定義個(gè)標(biāo)識 promise2是否已經(jīng)resolve 或 reject了
      ;let isThenCalled = false
      // 2.3.1 如果promise和x引用同一個(gè)對象赊级,則以TypeError為原因拒絕promise押框。
      ;if (promise2 === x) return reject(new TypeError('循環(huán)引用!@硌贰橡伞!'))
      // 2.3.2 如果x是一個(gè)promise,采用它的狀態(tài)【3.4
      ;if (x instanceof MyPromise) {
        /**
         * 2.3.2.1 如果x是初始態(tài)晋被,promise必須保持初始態(tài)(即遞歸執(zhí)行這個(gè)解決程序)兑徘,直到x被成功或被失敗。(即羡洛,直到resolve或者reject執(zhí)行)
         */
        if (x.status === 'pending') {
          x.then(function(y) {
            ;resolveExecutor(promise2, y, resolve, reject)
          }, reject)
        } else {
          // 2.3.2.2 如果/當(dāng)x被成功時(shí)道媚,用相同的值(結(jié)果)履行promise。
          // 2.3.2.3 如果/當(dāng)x被失敗時(shí)翘县,用相同的錯(cuò)誤原因履行promise。
          ;x.then(resolve, reject)
        }
      } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        // 2.3.3 否則谴分,如果x是一個(gè)對象或函數(shù),
        try {
          // 2.3.3.1 讓then等于x.then锈麸。【3.5】
          ;let then = x.then
          if (typeof then === 'function') {
            //2.3.3.3.3 如果resolvePromise和rejectPromise都被調(diào)用牺蹄,或者對同一個(gè)參數(shù)進(jìn)行多次調(diào)用忘伞,則第一次調(diào)用優(yōu)先,并且任何進(jìn)一步的調(diào)用都會(huì)被忽略。
            ;let resolvePromise = y => {
              //如果promise2已經(jīng)成功或失敗了氓奈,就return掉
              ;if (isThenCalled) return
              ;isThenCalled = true
              //2.3.3.3.1 如果使用值(結(jié)果)y調(diào)用resolvePromise翘魄,運(yùn)行[[Resolve]](promise,y)我的解決程序的名字是resolveExecutor,也就是遞歸調(diào)用舀奶。
              ;resolveExecutor(promise2, y, resolve, reject)
            }
            ;let rejectPromise = r => {
              //如果promise2已經(jīng)成功或失敗了暑竟,就return掉
              ;if (isThenCalled) return
              ;isThenCalled = true
              //2.3.3.3.2 如果使用拒絕原因r調(diào)用resolvePromise,運(yùn)行reject(r)育勺。
              ;reject(r)
            };
            // 2.3.3.3 如果then是一個(gè)函數(shù)但荤,則使用x作為此參數(shù)調(diào)用它,第一個(gè)參數(shù)resolveExecutor涧至,第二個(gè)參數(shù)rejectPromise腹躁,其中
            ;then.call(x, resolvePromise, rejectPromise)
          } else {
            //到此的話x不是一個(gè)thenable對象,那直接把它當(dāng)成值resolve promise2就可以了
            ;resolve(x)
          }
        } catch (e) {
          //2.3.3.3.4 如果調(diào)用then方法拋出異常e南蓬,
          //2.3.3.3.4.1 如果resolvePromise或rejectPromise已經(jīng)調(diào)用了纺非,則忽略它。
          ;if (isThenCalled) return
          ;isThenCalled = true

          //2.3.3.2 如果x.then導(dǎo)致拋出異常e赘方,拒絕promise并用e作為失敗原因
          //2.3.3.3.4.2 否則烧颖,以e作為失敗原因拒絕promise
          ;reject(e)
        }
      } else {
        //2.3.3.4 如果then不是一個(gè)對象或者函數(shù),則用x作為值(結(jié)果)履行promise蒜焊。
        ;resolve(x)
      }
    };
    if (self.status === 'fulfilled') {
      //2.2.7
      return (promise2 = new MyPromise((resolve, reject) => {
        //2.2.4 在執(zhí)行上下文堆棧僅包含平臺(tái)代碼之前倒信,不能調(diào)用onFulfilled或onRejected。[3.1]泳梆。
        //3.1 這里的“平臺(tái)代碼”是指引擎鳖悠,環(huán)境和primise實(shí)現(xiàn)代碼。在實(shí)踐中优妙,這個(gè)要求確保onFulfilled和onRejected異步執(zhí)行乘综,在事件循環(huán)開始之后then被調(diào)用,和一個(gè)新的堆棧套硼。這可以使用諸如setTimeout或setImmediate之類的“宏任務(wù)”機(jī)制卡辰,或者使用諸如MutationObserver或process.nextTick的“微任務(wù)”機(jī)制來實(shí)現(xiàn)。由于promise實(shí)現(xiàn)被認(rèn)為是經(jīng)過深思熟慮的平臺(tái)代碼邪意,因此它本身可能包含調(diào)用處理程序的任務(wù)調(diào)度隊(duì)列或或稱為“trampoline”(可重用的)的處理程序九妈。
        //讓onFulfilled異步執(zhí)行
        setTimeout(() => {
          try {
            ;let x = onFulfilled(self.value)
            ;resolveExecutor(promise2, x, resolve, reject)
          } catch (e) {
            ;reject(e)
          }
        })
      }))
    }
    if (self.status === 'rejected') {
      return (promise2 = new MyPromise((resolve, reject) => {
        //2.2.4 在執(zhí)行上下文堆棧僅包含平臺(tái)代碼之前,不能調(diào)用onFulfilled或onRejected雾鬼。[3.1]萌朱。
        //3.1 這里的“平臺(tái)代碼”是指引擎,環(huán)境和primise實(shí)現(xiàn)代碼策菜。在實(shí)踐中晶疼,這個(gè)要求確保onFulfilled和onRejected異步執(zhí)行酒贬,在事件循環(huán)開始之后then被調(diào)用,和一個(gè)新的堆棧翠霍。這可以使用諸如setTimeout或setImmediate之類的“宏任務(wù)”機(jī)制锭吨,或者使用諸如MutationObserver或process.nextTick的“微任務(wù)”機(jī)制來實(shí)現(xiàn)。由于promise實(shí)現(xiàn)被認(rèn)為是經(jīng)過深思熟慮的平臺(tái)代碼寒匙,因此它本身可能包含調(diào)用處理程序的任務(wù)調(diào)度隊(duì)列或或稱為“trampoline”(可重用的)的處理程序零如。
        //讓onFulfilled異步執(zhí)行
        setTimeout(() => {
          try {
            ;let x = onRejected(self.reason)
            ;resolveExecutor(promise2, x, resolve, reject)
          } catch (e) {
            ;reject(e)
          }
        })
      }))
    }
    if (self.status === 'pending') {
      return (promise2 = new MyPromise((resolve, reject) => {
        self.onResolvedCallbacks.push(() => {
          try {
            ;let x = onFulfilled(self.value)
            ;resolveExecutor(promise2, x, resolve, reject)
          } catch (e) {
            ;reject(e)
          }
        });
        self.onRejectedCallbacks.push(() => {
          try {
            ;let x = onRejected(self.reason)
            ;resolveExecutor(promise2, x, resolve, reject)
          } catch (e) {
            ;reject(e)
          }
        })
      }))
    }
  }
  catch(onRejected) {
    ;this.then(null, onRejected)
  }
  //立即成功的promise
static resolve(value) {
    return new MyPromise(resolve => {
      ;resolve(value)
    })
  }
  //立即失敗的promise
static reject(reason) {
    return new MyPromise((resolve, reject) => {
      ;reject(reason)
    })
  }
  //promise all方法,只要有一個(gè)失敗就失敗了蒋情。
static all(promises) {
    return new MyPromise((resolve, reject) => {
      ;let len = promises.length
      ;let resolveAry = []
      ;let count = 0
      for (let i = 0; i < len; i++) {
        promises[i].then(value => {
          ;resolveAry[i] = value
          ;if (++count === len) resolve(resolveAry)
        }, reject)
      }
    })
  }
  //promise all方法埠况,只要有一個(gè)失敗就失敗了。
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      for (let i = 0, l = promises.length; i < l; i++) {
        ;promises[i].then(resolve, reject)
      }
    })
  }
}
module.exports = MyPromise;

~~~ 如有不妥之處棵癣,歡迎大家留言指正辕翰,如覺得好請關(guān)注,點(diǎn)贊狈谊,轉(zhuǎn)發(fā)請注明出處喜命,謝謝! ~~~

郵箱:gameness1212@163.com

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末河劝,一起剝皮案震驚了整個(gè)濱河市壁榕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赎瞎,老刑警劉巖牌里,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異务甥,居然都是意外死亡牡辽,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門敞临,熙熙樓的掌柜王于貴愁眉苦臉地迎上來态辛,“玉大人,你說我怎么就攤上這事挺尿∽嗪冢” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵编矾,是天一觀的道長熟史。 經(jīng)常有香客問我,道長窄俏,這世上最難降的妖魔是什么以故? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮裆操,結(jié)果婚禮上怒详,老公的妹妹穿的比我還像新娘。我一直安慰自己踪区,他們只是感情好昆烁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缎岗,像睡著了一般静尼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上传泊,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天鼠渺,我揣著相機(jī)與錄音,去河邊找鬼眷细。 笑死拦盹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的溪椎。 我是一名探鬼主播普舆,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼校读!你這毒婦竟也來了沼侣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤歉秫,失蹤者是張志新(化名)和其女友劉穎蛾洛,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雁芙,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡轧膘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了却特。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扶供。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖裂明,靈堂內(nèi)的尸體忽然破棺而出椿浓,到底是詐尸還是另有隱情,我是刑警寧澤闽晦,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布扳碍,位于F島的核電站,受9級特大地震影響仙蛉,放射性物質(zhì)發(fā)生泄漏笋敞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一荠瘪、第九天 我趴在偏房一處隱蔽的房頂上張望夯巷。 院中可真熱鬧赛惩,春花似錦、人聲如沸趁餐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽后雷。三九已至季惯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間臀突,已是汗流浹背扮宠。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工骆捧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留岩睁,地道東北人翅雏。 一個(gè)月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像盒齿,于是被迫代替她去往敵國和親念逞。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi閱讀 7,322評論 0 10
  • 約德爾是個(gè)會(huì)打仗的將軍边翁,也是個(gè)軍人榮譽(yù)感極強(qiáng)的將軍翎承,一直到他被國際軍事法庭處死,他都把軍人這個(gè)職業(yè)當(dāng)成是自己的信仰...
    俏村姑閱讀 716評論 0 3
  • 8月1號至7號是一年一度的世界母乳喂養(yǎng)周符匾,它是國際母乳喂養(yǎng)行動(dòng)聯(lián)盟組織發(fā)起的一項(xiàng)全球性的活動(dòng)叨咖,目的是讓人們正確認(rèn)識...
    何少梅母指導(dǎo)樂閱讀 272評論 0 0
  • 我是一只海鳥 追逐波濤 輕撫浪花 我是一只海鳥 穿越大海 奔向光明 我是一只海鳥 深深眷戀 蔚藍(lán)大海 我是一只海鳥...
    舒潔湲閱讀 199評論 0 7