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

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

在 JavaScript 中創(chuàng)建您自己的 Promise

Dec 28, 2024 pm 01:29 PM

Create your own Promise in JavaScript

為什么?

了解 JavaScript Promises 如何在后臺(tái)異步運(yùn)行回調(diào)。

讓我們用 JavaScript 創(chuàng)建我們自己的 Promise!我們將遵循 Promise/A 規(guī)范,該規(guī)范概述了 Promise 如何處理異步操作、解析、拒絕以及確??深A(yù)測(cè)的鏈接和錯(cuò)誤處理。

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

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

1.1 'promise' 是一個(gè)帶有 then 方法的對(duì)象或函數(shù),其行為符合此規(guī)范。

1.2 thenable'是一個(gè)定義了then方法的對(duì)象或函數(shù)。

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

1.4 “異常”是使用 throw 語(yǔ)句拋出的值。

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

2. 要求

2.1 承諾狀態(tài)

承諾必須處于以下三種狀態(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)訪(fǎng)問(wèn)其當(dāng)前或最終的值或原因。

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

promise.then(onFulfilled, onRejected);

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

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

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

2.2.2。如果 onFulfilled 是一個(gè)函數(shù): ?

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

? 在承諾完成之前不得調(diào)用它。

? 不得多次調(diào)用。

2.2.3。如果 onRejected 是一個(gè)函數(shù),?

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

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

? 不得多次調(diào)用。

2.2.4。在執(zhí)行上下文堆棧僅包含平臺(tái)代碼之前,不得調(diào)用 onFulfilled 或 onRejected。 ?

2.2.5。 onFulfilled 和 onRejected 必須作為函數(shù)調(diào)用(即沒(méi)有 this 值)。 ?

2.2.6。 then 可能會(huì)針對(duì)同一個(gè) Promise 被多次調(diào)用。 ?

? 如果/當(dāng) Promise 被履行時(shí),所有相應(yīng)的 onFulfilled 回調(diào)必須按照它們最初調(diào)用 then 的順序執(zhí)行。

? 如果/當(dāng) Promise 被拒絕時(shí),所有相應(yīng)的 onRejected 回調(diào)必須按照其原始調(diào)用 then 的順序執(zhí)行。

2.2.7。那么必須返回一個(gè)承諾。 ?

promise.then(onFulfilled, onRejected);

? 如果 onFulfilled 或 onRejected 返回值 x,則運(yùn)行 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 采用執(zhí)行器函數(shù)作為參數(shù),該函數(shù)在 Promise 創(chuàng)建時(shí)立即調(diào)用:

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

核心 Promises/A 規(guī)范不涉及如何創(chuàng)建、履行或拒絕 Promise。由你決定。但是您為 Promise 構(gòu)造提供的實(shí)現(xiàn)必須與 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 必須處于以下三種狀態(tài)之一:待處理、已履行或已拒絕。它還解釋了每個(gè)狀態(tài)中發(fā)生的情況。

當(dāng)履行或拒絕時(shí),承諾不得轉(zhuǎn)變?yōu)槿魏纹渌麪顟B(tài)。因此,我們需要在進(jìn)行任何轉(zhuǎn)換之前確保 Promise 處于待處理狀態(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)造函數(shù)方法中調(diào)用它:

this.state = 'pending';

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

Promise/A 規(guī)范主要關(guān)注定義可互操作的 then() 方法。這個(gè)方法讓我們可以訪(fǎng)問(wèn)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ì)調(diào)用 onFulfilled 回調(diào)并使用 Promise 的值來(lái)解析它。同樣,如果 Promise 被拒絕,我們會(huì)調(diào)用 onRejected 回調(diào)并以 Promise 的原因拒絕它。

下一個(gè)問(wèn)題是,如果 Promise 仍處于待處理狀態(tài),如何處理 onFulfilled 和 onRejected 回調(diào)?我們將它們排隊(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)的隊(duì)列。當(dāng) Promise 未決時(shí),這些隊(duì)列通過(guò) then() 調(diào)用填充回調(diào),并且當(dāng) Promise 被履行或拒絕時(shí)調(diào)用它們。

繼續(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;
    }
};

另一方面,如果您運(yùn)行以下測(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)調(diào)用 then() 時(shí) YourPromise 實(shí)例已被解析或拒絕時(shí),then() 方法如何處理回調(diào)。具體來(lái)說(shuō),當(dāng) Promise 狀態(tài)不是待處理時(shí),then() 方法不會(huì)正確地將回調(diào)的執(zhí)行推遲到下一個(gè)微任務(wù)隊(duì)列。這會(huì)導(dǎo)致同步執(zhí)行。在我們的示例測(cè)試中:

? 承諾立即解決,值為“立即解決”。

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

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

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

這條規(guī)則是 Promise/A 規(guī)范中最重要的規(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ī)制中的回調(diào)將在當(dāng)前 JavaScript 執(zhí)行上下文完成后執(zhí)行。

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

promise.then(onFulfilled, onRejected);

再次運(yùn)行前面的示例測(cè)試代碼。您應(yīng)該得到以下輸出:

promise2 = promise1.then(onFulfilled, onRejected);

就是這樣。

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

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

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

關(guān)注我:
LinkedIn、Medium 和 Github

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

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系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

用于從照片中去除衣服的在線(xiàn)人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機(jī)

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)話(huà)題

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)用戶(hù)操作的時(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.替換重型依賴(lài),選用輕量級(jí)庫(kù)如day.js、fetch

See all articles