国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

使用Promise鏈式調用解決多個異步回調的問題

2019-11-19 17:56:01
字體:
來源:轉載
供稿:網友

介紹

所謂Promise,簡單來說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果。

缺少場景支撐,對于新手而言,很難理解Promise的意義。

在《你不知道的JavaScript中》有個場景介紹得很形象:

我走到快餐店的柜臺,點了一個芝士漢堡。我交給收銀員1.47美元。通過下訂單并付款,我已經發出了一個對某個值(就是那個漢堡)的請求。我已經啟 動了一次交易。

但是,通常我不能馬上就得到這個漢堡。收銀員會交給我某個東西來代替漢堡:一張帶有 訂單號的收據。訂單號就是一個 IOU(I owe you, 我欠你的)承諾(promise),保證了最 終我會得到我的漢堡。

所以我得好好保留我的收據和訂單號。我知道這代表了我未來的漢堡,所以不需要擔心, 只是現在我還是很餓!

在等待的過程中,我可以做點其他的事情,比如給朋友發個短信:“嗨,要來和我一起吃 午飯嗎?我正要吃芝士漢堡。”

我已經在想著未來的芝士漢堡了, 盡管現在我還沒有拿到手。 我的大腦之所以可以這么 做,是因為它已經把訂單號當作芝士漢堡的占位符了。從本質上講,這個占位符使得這個 值不再依賴時間。這是一個未來值。

終于, 我聽到服務員在喊“訂單 113” , 然后愉快地拿著收據走到柜臺, 把收據交給收銀 員,換來了我的芝士漢堡。

換句話說, 一旦我需要的值準備好了, 我就用我的承諾值(value-promise)換取這個值 本身。

但是,還可能有另一種結果。他們叫到了我的訂單號,但當我過去拿芝士漢堡的時候,收 銀員滿是歉意地告訴我:“不好意思,芝士漢堡賣完了。”除了作為顧客對這種情況感到憤 怒之外,我們還可以看到未來值的一個重要特性:它可能成功,也可能失敗。

每次點芝士漢堡,我都知道最終要么得到一個芝士漢堡,要么得到一個漢堡包售罄的壞消息,那我就得找點別的當午飯了。

所以Promise的出現其實是作為異步編程的一種解決方案。比傳統的解決方案-回調函數和事件-更加合理、強大。

Promise的基本用法

var p1 = new Promise((resolve, reject) => { setTimeout(resolve, 1000, 'done'); })p1.then(data=>{ console.log(data); // done})

Promise一個明顯的好處便是可以用來解決回調地獄。特別是在處理多個回調相互依賴的情況。

使用Promise解決多個異步依賴調用

Promise提供了一個方法Promise.all([p1,p2,p3]) ,用于將多個Promise實例,包裝成一個新的Promise實例。接收的參數是一個數組,p1、p2、p3都是Promise對象。

此時Promise.all的狀態取決于它的參數。

分兩種情況:

  • p1、p2、p3的狀態都是resolve的時候,Promise.all的狀態才會變成resolve;
  • 只要p1、p2、p3中有一個的狀態為reject,那么Promise.all的狀態就會變成reject;

所以我們可以用Promise.all()來解決多個異步依賴調用。

比如我們平常經常遇到的一種情況:

網站中需要先獲取用戶名,然后再根據用戶名去獲取用戶信息。這里獲取用戶名getUserName()和獲取用戶信息getUser()都是調用接口的異步請求。在獲取用戶信息之前,需要先獲得用戶名。也就是說getUser依賴于getUserName的狀態。所以我們可以將這兩個請求通過Promise.all()封裝成一個新的Promise對象。

function getUserPromise(promiseX, promiseY){ return Promise.all([promiseX, promiseY]) .then(values => // 返回的values由 promiseX 與 promiseY返回的值所構成的數組。  values )}function getUserName(){ let data = 'superman'; return new Promise((resolve, reject) => {  setTimeout(resolve(data), 1000); })}function getUser(){ let data = { id:1, username: 'superman', gender: 'male' } return new Promise((resolve, reject) => { setTimeout(resolve(data), 2000); })}getUserPromise(getUserName(), getUser()).then(data => { // 這里的data就是包含了getUserName 和 getUser返回值所組成的數組 console.log(data); // [ 'superman', { id: 1, username: 'superman', gender: 'male' } ] })

使用Promise的鏈式調用

function getUserName(){ let data = 'superman'; return new Promise((resolve, reject) => { setTimeout(resolve(data), 4000); })}function getUser(username){ let data = { id:1, username: 'superman', gender: 'male' } return new Promise((resolve, reject) => { if(username){  setTimeout(resolve(data), 2000); } else{  reject('err'); } })}getUserName().then(username => { return getUser();}).then(user => { console.log(user);}).catch(err => { console.log(err);})

有了Promise的鏈式調用,再也不同擔心回調地獄的問題了。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 通许县| 常宁市| 封开县| 如皋市| 墨竹工卡县| 连山| 来安县| 阿勒泰市| 普格县| 南木林县| 来安县| 连南| 蒙城县| 思南县| 安阳市| 隆化县| 巴青县| 略阳县| 乐亭县| 陵水| 斗六市| 乌兰浩特市| 惠东县| 厦门市| 嘉善县| 泰州市| 丰顺县| 东明县| 开化县| 高邑县| 潞西市| 绥芬河市| 瑞丽市| 呼伦贝尔市| 清河县| 平度市| 宁晋县| 昭苏县| 昌宁县| 宁津县| 德化县|