App下載

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

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

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

JavaScript 中的 Promise 是什么?

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

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

無賴,對吧?

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

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

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

“成功了,我找到了你的簡歷!”

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

“抱歉,我找不到你的簡歷,因?yàn)槟惚kU箱的鑰匙不見了。”

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

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

他的室友終于回了短信。正如我們之前討論過的,如果他沒有找到簡歷,他會與您分享這次失敗以及他沒有找到的原因。

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

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

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

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

JavaScript 中的 promise 是異步的,這意味著它需要時間來解決或完成。正如搜索申請人的簡歷需要時間來完成一樣。

出于這個原因,面試官決定不坐下來無所事事,所以他們根據(jù)投遞簡歷的承諾開始面試候選人。我們正在使用返回簡歷代替實(shí)際簡歷的promise。

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

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

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

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

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

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

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

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

如何在 JavaScript 中編寫 Promise

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

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

console.log(myPromise);
在控制臺中運(yùn)行它會返回一個?Promise?對象:

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

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

console.log(anotherPromise);

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

JavaScript 中的拒絕promise

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

這是一個簡單而人為的例子,說明了 Promise 是如何被拒絕的:

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

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

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

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

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

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

您可以定義兩個回調(diào)函數(shù),當(dāng)promise被實(shí)現(xiàn)或被拒絕時,您希望調(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)行此代碼將在三秒鐘后在控制臺中顯示完成消息:

請注意,您可以根據(jù)需要嵌套任意數(shù)量的 promise。每一步都會在上一步之后執(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) })

但是我們錯過了一些重要的事情。

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

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

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

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

?catch()?每當(dāng)在承諾鏈中的任何一點(diǎn)遇到錯誤時,都會調(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最終會解析為拒絕,因此嵌套中定義的函數(shù)?then()?將被忽略。相反,錯誤處理程序?catch()?將運(yùn)行,它應(yīng)該將以下錯誤消息記錄到控制臺:

總結(jié)

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

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

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


0 人點(diǎn)贊