App下載

什么是promise?初學(xué)者怎么理解+ JavaScript promise?

花式作死冠軍 2021-08-24 14:30:07 瀏覽數(shù) (3548)
反饋

如果您是 JavaScript 初學(xué)者,您可能很難理解 Promise 的真正含義。我已經(jīng)閱讀了很多關(guān)于 Promise 的文章,但問(wèn)題是這些指南中的許多都沒(méi)有以相關(guān)的方式解釋它們。人們不理解 JavaScript 中的 promise 是因?yàn)樗麄儾⒉徽嬲私馑暮x以及它在簡(jiǎn)單和相關(guān)的術(shù)語(yǔ)中的行為方式。所以在這篇文章中,我將告訴你一個(gè)簡(jiǎn)短的故事,它解釋了 Promise 是什么以及它們是如何工作的。我還將通過(guò)一些示例向您展示如何在 JavaScript 中使用 promise。

JavaScript 中的 Promise 是什么?

想象一下,您正在為您公司的某個(gè)職位面試求職者。

一個(gè)年輕人瘋狂地進(jìn)來(lái)接受采訪。當(dāng)他的面試即將開(kāi)始時(shí),他意識(shí)到自己忘記了簡(jiǎn)歷。

無(wú)賴,對(duì)吧?

不過(guò),他并不氣餒。幸運(yùn)的是,他有一個(gè)當(dāng)時(shí)還在家里的室友。

他迅速通過(guò)電話給他的室友打電話,向他尋求幫助。他懇求他的室友幫忙找他的簡(jiǎn)歷。他的室友答應(yīng)他一有事情要報(bào)告就回短信。

假設(shè)最終找到了簡(jiǎn)歷,他可以回短信:

“成功了,我找到了你的簡(jiǎn)歷!”

但如果他沒(méi)有找到,他應(yīng)該發(fā)回一條失敗信息,說(shuō)明他找不到簡(jiǎn)歷的原因。例如,他可能會(huì)將此消息發(fā)送給正在面試的朋友:

“抱歉,我找不到你的簡(jiǎn)歷,因?yàn)槟惚kU(xiǎn)箱的鑰匙不見(jiàn)了?!?/blockquote>

與此同時(shí),面試按計(jì)劃繼續(xù)進(jìn)行,面試官堅(jiān)持找到簡(jiǎn)歷的promise,而不是實(shí)際的簡(jiǎn)歷。此時(shí),面試官將投遞簡(jiǎn)歷的狀態(tài)設(shè)置為 PENDING。

受訪者回答了他被問(wèn)到的所有問(wèn)題。但歸根結(jié)底,他的就業(yè)仍然取決于他簡(jiǎn)歷的最終狀態(tài)。

他的室友終于回了短信。正如我們之前討論過(guò)的,如果他沒(méi)有找到簡(jiǎn)歷,他會(huì)與您分享這次失敗以及他沒(méi)有找到的原因。

當(dāng)這種情況發(fā)生時(shí),面試將結(jié)束,面試者將被拒絕。

另一方面,如果室友找到了簡(jiǎn)歷,他會(huì)很高興地告訴他的朋友他成功了,他會(huì)繼續(xù)前進(jìn),實(shí)現(xiàn)他找到工作的希望。

那么這如何轉(zhuǎn)換為 JS 代碼呢?

promise找到簡(jiǎn)歷并發(fā)短信的室友與我們?nèi)绾卧?JavaScript 中定義promise是同義詞。代碼不會(huì)直接或立即返回值。相反,它返回一個(gè)promise,它最終將在以后提供該值。

JavaScript 中的 promise 是異步的,這意味著它需要時(shí)間來(lái)解決或完成。正如搜索申請(qǐng)人的簡(jiǎn)歷需要時(shí)間來(lái)完成一樣。

出于這個(gè)原因,面試官?zèng)Q定不坐下來(lái)無(wú)所事事,所以他們根據(jù)投遞簡(jiǎn)歷的承諾開(kāi)始面試候選人。我們正在使用返回簡(jiǎn)歷代替實(shí)際簡(jiǎn)歷的promise。

JS 引擎也不會(huì)等待什么都不做——它開(kāi)始執(zhí)行代碼的其他部分,等待 promise 的返回值。

消息文本包含簡(jiǎn)歷搜索的狀態(tài)消息。對(duì)于 JavaScript Promise,這也稱為返回值。

如果消息是“成功”,我們將繼續(xù)簽署候選人并授予他職位。如果失敗,我們將繼續(xù)拒絕他的申請(qǐng)。

對(duì)于 JavaScript 承諾,我們通過(guò)使用回調(diào)函數(shù)(promise處理程序)來(lái)做到這一點(diǎn)。這些函數(shù)在嵌套?then()?方法中定義。

要指定要調(diào)用的回調(diào),請(qǐng)使用以下兩個(gè)函數(shù):

  • ?resolve(value)?:這表示異步任務(wù)成功。這將調(diào)用?then()?處理程序中的履行回調(diào)。
  • ?reject(error)?:這表示嘗試運(yùn)行異步任務(wù)時(shí)出錯(cuò)。這將在?then()?處理程序中調(diào)用拒絕回調(diào)。

如果promise成功,將調(diào)用履行回調(diào)。如果promise被拒絕,則將調(diào)用被拒絕的回調(diào)。

promise只是一個(gè)尚未完成的異步任務(wù)的占位符。當(dāng)您在腳本中定義一個(gè) promise 對(duì)象時(shí),它不會(huì)立即返回一個(gè)值,而是返回一個(gè) promise。

如何在 JavaScript 中編寫 Promise

您可以通過(guò)調(diào)用?Promise?該類并構(gòu)造這樣的對(duì)象在 JavaScript 中定義promise:

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('this is the eventual value the promise will return');
  }, 300);
});

console.log(myPromise);
在控制臺(tái)中運(yùn)行它會(huì)返回一個(gè)?Promise?對(duì)象:

不過(guò),構(gòu)造一個(gè)對(duì)象并不是定義 Promise 的唯一方法。您還可以使用內(nèi)置?Promise?API 來(lái)實(shí)現(xiàn)相同的功能:

const anotherPromise = Promise.resolve("this is the eventual value the promise will return")

console.log(anotherPromise);

雖然第一個(gè)代碼示例中的 Promise 會(huì)等待 3 秒,然后才使用?this is the eventual...?消息實(shí)現(xiàn) Promise,但第二個(gè)代碼示例中的 Promise 將立即使用相同的消息實(shí)現(xiàn)它。

JavaScript 中的拒絕promise

Promise 也可以被拒絕。大多數(shù)情況下,拒絕發(fā)生是因?yàn)?JS 在運(yùn)行異步代碼時(shí)遇到某種錯(cuò)誤。在這種情況下,它會(huì)調(diào)用該?reject()?函數(shù)。

這是一個(gè)簡(jiǎn)單而人為的例子,說(shuō)明了 Promise 是如何被拒絕的:

const myPromise = new Promise((resolve, reject) => {
  let a = false;
  setTimeout(() => {
    return (a) ? resolve('a is found!'): reject('sorry, no a');
  }, 300);
}); 

你能想出這個(gè)promise被拒絕的原因嗎?如果你說(shuō)“因?yàn)閍不是假的”,恭喜!

第三個(gè)代碼示例中的 promise 將在三秒超時(shí)后解析為拒絕,因?yàn)樵?(a)??語(yǔ)句解析為 ?false?,這將觸發(fā)?reject?.

如何訪問(wèn) then()中的先前的Promise結(jié)果

當(dāng) Promise 最終返回一個(gè)值時(shí),您通常希望對(duì)該返回值執(zhí)行一些操作。

例如,如果您正在發(fā)出網(wǎng)絡(luò)請(qǐng)求,您可能希望訪問(wèn)該值并將其顯示在用戶的頁(yè)面上。

您可以定義兩個(gè)回調(diào)函數(shù),當(dāng)promise被實(shí)現(xiàn)或被拒絕時(shí),您希望調(diào)用它們。這些函數(shù)在嵌套?then()?方法中定義:

const anotherPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('this is the eventual value the promise will return');
  }, 300);
});

// CONTINUATION
anotherPromise
.then(value => { console.log(value) }) 

運(yùn)行此代碼將在三秒鐘后在控制臺(tái)中顯示完成消息:

請(qǐng)注意,您可以根據(jù)需要嵌套任意數(shù)量的 promise。每一步都會(huì)在上一步之后執(zhí)行,取上一步的返回值:

const anotherPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('this is the eventual value the promise will return');
  }, 300);
});

anotherPromise
.then(fulfillFn, rejectFn)
.then(fulfilFn, rejectFn)
.then(value => { console.log(value) })

但是我們錯(cuò)過(guò)了一些重要的事情。

始終牢記一個(gè)?then()?方法必須同時(shí)接受執(zhí)行處理程序和拒絕處理程序。這樣,如果 Promise 得到滿足,則調(diào)用第一個(gè),如果 Promise 因錯(cuò)誤而被拒絕,則調(diào)用第二個(gè)。

代碼示例 4 和 5 中的 promise 不包含第二個(gè)處理程序。因此,假設(shè)遇到錯(cuò)誤,將沒(méi)有拒絕處理程序來(lái)處理錯(cuò)誤。

如果您只想在 中定義一個(gè)回調(diào)函數(shù)(又名完成處理程序)?then()?,那么您將需要?catch()?在 Promise 鏈的底部嵌套一個(gè)方法來(lái)捕獲任何可能的錯(cuò)誤。

如何在JS中使用catch()方法

?catch()?每當(dāng)在承諾鏈中的任何一點(diǎn)遇到錯(cuò)誤時(shí),都會(huì)調(diào)用該方法:

const myPromise = new Promise((resolve, reject) => {
  let a = false;
  setTimeout(() => {
    return (a) ? resolve('a is found!'): reject('sorry, no a');
  }, 300);
}); 

myPromise
.then(value => { console.log(value) })
.catch(err => { console.log(err) });

由于myPromise最終會(huì)解析為拒絕,因此嵌套中定義的函數(shù)?then()?將被忽略。相反,錯(cuò)誤處理程序?catch()?將運(yùn)行,它應(yīng)該將以下錯(cuò)誤消息記錄到控制臺(tái):

總結(jié)

JavaScript 承諾是一項(xiàng)非常強(qiáng)大的功能,可幫助您在 JavaScript 中運(yùn)行異步代碼。在大多數(shù)(如果不是全部)使用 JavaScript 的角色面試中,您的面試官可能會(huì)問(wèn)一個(gè)關(guān)于 promise 的問(wèn)題。

在本文中,我用簡(jiǎn)單的術(shù)語(yǔ)解釋了 promise 的含義,并通過(guò)一些代碼示例展示了它的基本實(shí)際用法。

我希望你從這篇文章中得到一些有用的東西。如果你喜歡這樣的編程相關(guān)教程,可以持續(xù)關(guān)注W3Cschool。


0 人點(diǎn)贊