国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁(yè) web前端 js教程 在 JavaScript 中建立您自己的 Promise

在 JavaScript 中建立您自己的 Promise

Dec 28, 2024 pm 01:29 PM

Create your own Promise in JavaScript

為什麼?

了解 JavaScript Promises 如何在背景非同步執(zhí)行回呼。

讓我們用 JavaScript 創(chuàng)建自己的 Promise!我們將遵循 Promise/A 規(guī)範(fàn),該規(guī)範(fàn)概述了 Promise 如何處理非同步操作、解析、拒絕以及確保可預(yù)測(cè)的連結(jié)和錯(cuò)誤處理。

為了簡(jiǎn)單起見(jiàn),我們將重點(diǎn)放在 Promises/A 規(guī)範(fàn)中 ? 標(biāo)記的關(guān)鍵規(guī)則。這不是一個(gè)完整的實(shí)現(xiàn),而是一個(gè)簡(jiǎn)化版本。這是我們將要建構(gòu)的:

1. 術(shù)語(yǔ)

1.1 'promise' 是一個(gè)帶有 then 方法的物件或函數(shù),其行為符合此規(guī)範(fàn)。

1.2 thenable'是一個(gè)定義了then方法的物件或函數(shù)。

1.3 'value' 是任何合法的 JavaScript 值(包括未定義的、thenable 或一個(gè)promise)。

1.4 「異?!故鞘褂?throw 語(yǔ)句拋出的值。

1.5 'reason' 是一個(gè)值,表示承諾被拒絕的原因。

2. 要求

2.1 承諾狀態(tài)

承諾必須處?kù)兑韵氯N狀態(tài)之一:待定、已履行或已拒絕。

2.1.1。待處理時(shí),承諾:?

? 可能會(huì)轉(zhuǎn)換為已完成或已拒絕狀態(tài)。

2.1.2。兌現(xiàn)後,承諾:?

?不得轉(zhuǎn)換到任何其他狀態(tài)。

? 必須有一個(gè)值,且不得更改。

2.1.3。當(dāng)被拒絕時(shí),一個(gè)承諾:?

?不得轉(zhuǎn)換到任何其他狀態(tài)。

?必須有一個(gè)理由,而這個(gè)理由不能改變。

2.2 then方法

promise 必須提供 then 方法來(lái)存取其當(dāng)前或最終的值或原因。

promise 的 then 方法接受兩個(gè)參數(shù):

promise.then(onFulfilled, onRejected);

2.2.1。 onFulfilled 和 onRejected 都是可選參數(shù):?

? 如果 onFulfilled 不是函數(shù),則必須忽略它。

? 如果 onRejected 不是函數(shù),則必須忽略它。

2.2.2。如果 onFulfilled 是函數(shù): ?

? 它必須在 Promise 完成後調(diào)用,並以 Promise 的值作為第一個(gè)參數(shù)。

? 在承諾完成之前不得呼叫它。

? 不得多次呼叫。

2.2.3。如果 onRejected 是函數(shù),?

? 它必須在 Promise 被拒絕後調(diào)用,並以 Promise 的原因作為第一個(gè)參數(shù)。

? 在承諾被拒絕之前不得調(diào)用它。

? 不得多次呼叫。

2.2.4。在執(zhí)行上下文堆疊僅包含平臺(tái)程式碼之前,不得呼叫 onFulfilled 或 onRejected。 ?

2.2.5。 onFulfilled 和 onRejected 必須作為函數(shù)呼叫(即沒(méi)有 this 值)。 ?

2.2.6。 then 可能會(huì)針對(duì)同一個(gè) Promise 被多次呼叫。 ?

? 如果/當(dāng) Promise 被履行時(shí),所有對(duì)應(yīng)的 onFulfilled 回呼必須按照它們最初呼叫 then 的順序執(zhí)行。

? 如果/當(dāng) Promise 被拒絕時(shí),所有對(duì)應(yīng)的 onRejected 回呼必須按照其原始呼叫 then 的順序執(zhí)行。

2.2.7。那就必須回傳一個(gè)承諾。 ?

promise.then(onFulfilled, onRejected);

? 如果 onFulfilled 或 onRejected 傳回值 x,則執(zhí)行 Promise 解析過(guò)程 [[Resolve]](promise2, x)。 ?

? 如果 onFulfilled 或 onRejected 拋出例外 e,則 Promise2 必須以 e 作為原因被拒絕。 ?

? 如果 onFulfilled 不是函數(shù)且 Promise1 已實(shí)現(xiàn),則 Promise2 必須以與 Promise1 相同的值來(lái)實(shí)現(xiàn)。 ?

? 如果 onRejected 不是函數(shù)且 Promise1 被拒絕,則 Promise2 也必須以與 Promise1 相同的原因被拒絕。 ?

執(zhí)行

JavaScript Promise 採(cǎi)用執(zhí)行器函數(shù)作為參數(shù),函數(shù)在 Promise 建立時(shí)立即呼叫:

promise2 = promise1.then(onFulfilled, onRejected);
new Promise(excecutor);

核心 Promises/A 規(guī)範(fàn)不涉及如何建立、履行或拒絕 Promise。由你決定。但是您為 Promise 建構(gòu)提供的實(shí)作必須與 JavaScript 中的非同步 API 相容。這是我們 Promise 類(lèi)別的初稿:

const promise = new Promise((resolve, reject) => {
    // Runs some async or sync tasks
});

規(guī)則 2.1(Promise 狀態(tài))規(guī)定,Promise 必須處?kù)兑韵氯N狀態(tài)之一:待處理、已履行或已拒絕。它還解釋了每個(gè)狀態(tài)中發(fā)生的情況。

當(dāng)履行或拒絕時(shí),承諾不得轉(zhuǎn)變?yōu)槿魏纹渌麪顟B(tài)。因此,我們需要在進(jìn)行任何轉(zhuǎn)換之前確保 Promise 處?kù)洞幚頎顟B(tài):

class YourPromise {
    constructor(executor) {
        this.state = 'pending';
        this.value = undefined;
        this.reason = undefined;

        const resolve = value => {
            if (this.state === 'pending') {
                this.state = 'fulfilled';
                this.value = value;
            }
        };

        const reject = reason => {
            if (this.state === 'pending') {
                this.state = 'rejected';
                this.reason = reason;
            }
        };

        try {
            executor(resolve, reject);  // The executor function being called immediately
        } catch (error) {
            reject(error);
        }
    }
}

我們已經(jīng)知道 Promise 的初始狀態(tài)是待處理的,並且我們確保它保持這種狀態(tài),直到明確履行或拒絕:

const resolve = value => {
    if (this.state === 'pending') {
        this.state = 'fulfilled';
        this.value = value;
    }
};

const reject = reason => {
    if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
    }
};

由於執(zhí)行器函數(shù)在 Promise 實(shí)例化後立即被調(diào)用,因此我們?cè)诮?gòu)子方法中調(diào)用它:

this.state = 'pending';

我們的 YourPromise 類(lèi)別的初稿已在此處完成。

Promise/A 規(guī)範(fàn)主要著重於定義可互通的 then() 方法。這個(gè)方法讓我們可以存取promise的當(dāng)前或最終值或原因。讓我們深入探討一下。

規(guī)則 2.2(Then 方法)規(guī)定 Promise 必須有一個(gè) then() 方法,該方法接受兩個(gè)參數(shù):

try {
    executor(resolve, reject);
} catch (error) {
    reject(error);
}

onFulfilled 和 onRejected 都必須在 Promise 完成或拒絕後調(diào)用,如果它們是函數(shù),則傳遞 Promise 的值或原因作為它們的第一個(gè)參數(shù):

class YourPromise {
    constructor(executor) {
        // Implementation
    }

    then(onFulfilled, onRejected) {
        // Implementation
    }
}

此外,在承諾履行或拒絕之前,不得調(diào)用它們,也不得調(diào)用超過(guò)一次。 onFulfilled 和 onRejected 都是可選的,如果它們不是函數(shù),則應(yīng)忽略它們。

如果你看規(guī)則2.2、2.2.6 和2.2.7,你會(huì)發(fā)現(xiàn)一個(gè)Promise 必須有一個(gè)then() 方法,then() 方法可以被多次調(diào)用,並且它必須返回一個(gè)承諾:

promise.then(onFulfilled, onRejected);

為了簡(jiǎn)單起見(jiàn),我們不會(huì)處理單獨(dú)的類(lèi)別或函數(shù)。我們將傳回一個(gè) Promise 對(duì)象,並傳遞一個(gè)執(zhí)行器函數(shù):

promise2 = promise1.then(onFulfilled, onRejected);

在執(zhí)行器函數(shù)中,如果 Promise 被履行,我們會(huì)呼叫 onFulfilled 回呼並使用 Promise 的值來(lái)解析它。同樣,如果 Promise 被拒絕,我們會(huì)呼叫 onRejected 回呼並以 Promise 的原因拒絕它。

下一個(gè)問(wèn)題是,如果 Promise 仍處?kù)洞幚頎顟B(tài),如何處理 onFulfilled 和 onRejected 回呼?我們將它們排隊(duì)以便稍後調(diào)用,如下所示:

new Promise(excecutor);

我們完成了。這是 Promise 類(lèi)別的第二稿,包括 then() 方法:

const promise = new Promise((resolve, reject) => {
    // Runs some async or sync tasks
});

這裡,我們引入兩個(gè)欄位:onFulfilledCallbacks 和 onRejectedCallbacks 作為保存回調(diào)的佇列。當(dāng) Promise 未決時(shí),這些佇列會(huì)透過(guò) then() 呼叫填入回調(diào),並且當(dāng) Promise 被履行或拒絕時(shí)呼叫它們。

繼續(xù)測(cè)試你的 Promise 類(lèi)別:

class YourPromise {
    constructor(executor) {
        this.state = 'pending';
        this.value = undefined;
        this.reason = undefined;

        const resolve = value => {
            if (this.state === 'pending') {
                this.state = 'fulfilled';
                this.value = value;
            }
        };

        const reject = reason => {
            if (this.state === 'pending') {
                this.state = 'rejected';
                this.reason = reason;
            }
        };

        try {
            executor(resolve, reject);  // The executor function being called immediately
        } catch (error) {
            reject(error);
        }
    }
}

它應(yīng)該輸出:

const resolve = value => {
    if (this.state === 'pending') {
        this.state = 'fulfilled';
        this.value = value;
    }
};

const reject = reason => {
    if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
    }
};

另一方面,如果您執(zhí)行以下測(cè)試:

this.state = 'pending';

你會(huì)得到:

try {
    executor(resolve, reject);
} catch (error) {
    reject(error);
}

代替:

class YourPromise {
    constructor(executor) {
        // Implementation
    }

    then(onFulfilled, onRejected) {
        // Implementation
    }
}

為什麼?問(wèn)題在於,當(dāng)呼叫 then() 時(shí) YourPromise 實(shí)例已被解析或拒絕時(shí),then() 方法如何處理回呼。具體來(lái)說(shuō),當(dāng) Promise 狀態(tài)不是待處理時(shí),then() 方法不會(huì)正確地將回呼的執(zhí)行延遲到下一個(gè)微任務(wù)佇列。這會(huì)導(dǎo)致同步執(zhí)行。在我們的範(fàn)例測(cè)試中:

? 承諾立即解決,值為「立即解決」。

? 當(dāng)呼叫promise.then()時(shí),狀態(tài)已經(jīng)完成,所以onFulfilled回呼會(huì)直接執(zhí)行,不會(huì)延遲到下一個(gè)微任務(wù)佇列。

這裡規(guī)則 2.2.4 發(fā)揮作用。此規(guī)則可確保 then() 回呼(onFulfilled 或 onRejected)非同步執(zhí)行,即使 Promise 已解決或拒絕。這意味著回調(diào)不得運(yùn)行,直到當(dāng)前執(zhí)行堆疊完全清除並且只有平臺(tái)程式碼(如事件循環(huán)或微任務(wù)佇列)正在運(yùn)行。

為什麼這條規(guī)則很重要?

這條規(guī)則是 Promise/A 規(guī)範(fàn)中最重要的規(guī)則之一。因?yàn)樗_保:

? 即使 Promise 立即解決,其 then() 回調(diào)也不會(huì)執(zhí)行,直到事件循環(huán)的下一個(gè)標(biāo)記。

? 此行為與 JavaScript 中其他非同步 API(例如 setTimeout 或 process.nextTick)的行為一致。

我們?cè)鯓硬拍茏龅竭@一點(diǎn)?

這可以透過(guò)巨集任務(wù)機(jī)制(如setTimeout或setImmediate)或微任務(wù)機(jī)制(如queueMicrotask或process.nextTick)來(lái)實(shí)現(xiàn)。因?yàn)槲⑷蝿?wù)或巨集任務(wù)或類(lèi)似機(jī)制中的回呼將在目前 JavaScript 執(zhí)行上下文完成後執(zhí)行。

為了解決上述問(wèn)題,我們需要確保即使?fàn)顟B(tài)已經(jīng)完成或拒絕,相應(yīng)的回調(diào)(onFulfilled或onRejected)也使用queueMicrotask非同步執(zhí)行。這是修正後的實(shí)作:

promise.then(onFulfilled, onRejected);

再次執(zhí)行前面的範(fàn)例測(cè)試程式碼。您應(yīng)該得到以下輸出:

promise2 = promise1.then(onFulfilled, onRejected);

就是這樣。

現(xiàn)在,您應(yīng)該清楚地了解 then() 的回調(diào)如何延遲並在下一個(gè)微任務(wù)佇列中執(zhí)行,從而實(shí)現(xiàn)異步行為。牢牢掌握這個(gè)概念對(duì)於在 JavaScript 中編寫(xiě)有效的非同步程式碼至關(guān)重要。

下一步是什麼?由於本文沒(méi)有涵蓋完整的 Promises/A 規(guī)範(fàn),您可以嘗試實(shí)現(xiàn)其餘部分以獲得更深入的理解。

既然你已經(jīng)讀到這裡了,希望你喜歡閱讀這篇文章!請(qǐng)分享文章。

追蹤我:
LinkedIn、Medium 和 Github

以上是在 JavaScript 中建立您自己的 Promise的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開(kāi)發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

熱門(mén)話題

Java vs. JavaScript:清除混亂 Java vs. JavaScript:清除混亂 Jun 20, 2025 am 12:27 AM

Java和JavaScript是不同的編程語(yǔ)言,各自適用於不同的應(yīng)用場(chǎng)景。 Java用於大型企業(yè)和移動(dòng)應(yīng)用開(kāi)發(fā),而JavaScript主要用於網(wǎng)頁(yè)開(kāi)發(fā)。

JavaScript評(píng)論:簡(jiǎn)短說(shuō)明 JavaScript評(píng)論:簡(jiǎn)短說(shuō)明 Jun 19, 2025 am 12:40 AM

JavascriptconcommentsenceenceEncorenceEnterential gransimenting,reading and guidingCodeeXecution.1)單inecommentsareusedforquickexplanations.2)多l(xiāng)inecommentsexplaincomplexlogicorprovideDocumentation.3)

如何在JS中與日期和時(shí)間合作? 如何在JS中與日期和時(shí)間合作? Jul 01, 2025 am 01:27 AM

JavaScript中的日期和時(shí)間處理需注意以下幾點(diǎn):1.創(chuàng)建Date對(duì)像有多種方式,推薦使用ISO格式字符串以保證兼容性;2.獲取和設(shè)置時(shí)間信息可用get和set方法,注意月份從0開(kāi)始;3.手動(dòng)格式化日期需拼接字符串,也可使用第三方庫(kù);4.處理時(shí)區(qū)問(wèn)題建議使用支持時(shí)區(qū)的庫(kù),如Luxon。掌握這些要點(diǎn)能有效避免常見(jiàn)錯(cuò)誤。

為什麼要將標(biāo)籤放在的底部? 為什麼要將標(biāo)籤放在的底部? Jul 02, 2025 am 01:22 AM

PlacingtagsatthebottomofablogpostorwebpageservespracticalpurposesforSEO,userexperience,anddesign.1.IthelpswithSEObyallowingsearchenginestoaccesskeyword-relevanttagswithoutclutteringthemaincontent.2.Itimprovesuserexperiencebykeepingthefocusonthearticl

JavaScript與Java:開(kāi)發(fā)人員的全面比較 JavaScript與Java:開(kāi)發(fā)人員的全面比較 Jun 20, 2025 am 12:21 AM

JavaScriptIspreferredforredforwebdevelverment,而Javaisbetterforlarge-ScalebackendsystystemsandSandAndRoidApps.1)JavascriptexcelcelsincreatingInteractiveWebexperienceswebexperienceswithitswithitsdynamicnnamicnnamicnnamicnnamicnemicnemicnemicnemicnemicnemicnemicnemicnddommanipulation.2)

什麼是在DOM中冒泡和捕獲的事件? 什麼是在DOM中冒泡和捕獲的事件? Jul 02, 2025 am 01:19 AM

事件捕獲和冒泡是DOM中事件傳播的兩個(gè)階段,捕獲是從頂層向下到目標(biāo)元素,冒泡是從目標(biāo)元素向上傳播到頂層。 1.事件捕獲通過(guò)addEventListener的useCapture參數(shù)設(shè)為true實(shí)現(xiàn);2.事件冒泡是默認(rèn)行為,useCapture設(shè)為false或省略;3.可使用event.stopPropagation()阻止事件傳播;4.冒泡支持事件委託,提高動(dòng)態(tài)內(nèi)容處理效率;5.捕獲可用於提前攔截事件,如日誌記錄或錯(cuò)誤處理。了解這兩個(gè)階段有助於精確控制JavaScript響應(yīng)用戶操作的時(shí)機(jī)和方式。

JavaScript:探索用於高效編碼的數(shù)據(jù)類(lèi)型 JavaScript:探索用於高效編碼的數(shù)據(jù)類(lèi)型 Jun 20, 2025 am 12:46 AM

javascripthassevenfundaMentalDatatypes:數(shù)字,弦,布爾值,未定義,null,object和symbol.1)numberSeadUble-eaduble-ecisionFormat,forwidevaluerangesbutbecautious.2)

如何減少JavaScript應(yīng)用程序的有效載荷大小? 如何減少JavaScript應(yīng)用程序的有效載荷大小? Jun 26, 2025 am 12:54 AM

如果JavaScript應(yīng)用加載慢、性能差,問(wèn)題往往出在payload太大,解決方法包括:1.使用代碼拆分(CodeSplitting),通過(guò)React.lazy()或構(gòu)建工具將大bundle拆分為多個(gè)小文件,按需加載以減少首次下載量;2.移除未使用的代碼(TreeShaking),利用ES6模塊機(jī)制清除“死代碼”,確保引入的庫(kù)支持該特性;3.壓縮和合併資源文件,啟用Gzip/Brotli和Terser壓縮JS,合理合併文件並優(yōu)化靜態(tài)資源;4.替換重型依賴,選用輕量級(jí)庫(kù)如day.js、fetch

See all articles