摘要:和的關(guān)系和的關(guān)系非常的巧妙,必須在內(nèi)使用,并裝飾一個(gè)對(duì)象,返回的也是一個(gè)對(duì)象。的會(huì)使得的代碼節(jié)點(diǎn)自動(dòng)拋出相應(yīng)的異常,終止向下繼續(xù)執(zhí)行。示例方法內(nèi)無節(jié)點(diǎn)沒有修飾的方法內(nèi)有節(jié)點(diǎn)注意內(nèi)的對(duì)節(jié)點(diǎn)的作用。
假設(shè)我們有三個(gè)請(qǐng)求,req1,req2, req3,三個(gè)請(qǐng)求后者依賴前者的請(qǐng)求結(jié)果。我們先使用Promise封裝一個(gè)異步請(qǐng)求的方法。
Promise 異步請(qǐng)求使用Promise可以非常容易的封裝一個(gè)異步處理的業(yè)務(wù),通過reslove/reject兩個(gè)callback來返回執(zhí)行結(jié)果。
我們使用 Promise 封裝一個(gè) http get方法。
// 返回一個(gè) Promise 對(duì)象(PromiseStatus: pending) function asyncHttpGet(url) { return new Promise((resolve, reject) => { const request = new Request(url, {method: "GET"}) // 使用 fetch 請(qǐng)求 fetch(request) .then(response => { if (200 == response.status) { return response.text() } else { // goto catch throw new Error("request failed: " + response.status) } }).then(html => { // console.log(html) resolve(url + " get success") }).catch(err => { reject(err) }); }) }
fetch返回的其實(shí)就是一個(gè)Promise對(duì)象,上例是想演示下resolve/reject的使用上下文,如果你早已get,下面給出直接使用fetch的方式:
async function asyncHttpGetV2(url) { const request = new Request(url, {method: "GET"}) try { let res = await fetch(request) .then(response => response.blob()) .then(blob => { console.log(blob) // Promise resolve return blob }).catch(err => { // Promise resolve throw err }); // Promise resolve return res; } catch (err) { // Promise reject throw err } }
可以發(fā)現(xiàn),fetch中return 代替了resolve,throw代替了reject,而async同fetch一樣,也是返回了一個(gè) Promise對(duì)象,所以async中的return/throw是否也會(huì)與自己的返回的Promise對(duì)象有關(guān)系呢?
回調(diào)地獄Promise 可以優(yōu)雅的實(shí)現(xiàn)異步,但 Promise.then().catch() 的鏈?zhǔn)浇Y(jié)構(gòu)也帶來了回調(diào)地獄的問題。如下,我們回調(diào)了3層,才能開始寫業(yè)務(wù)邏輯。
var url = window.location.href // 雖然異步了 但 callback hell asyncHttpGet(url).then(res => { var res1 = res asyncHttpGet(url).then(res => { var res2 = res asyncHttpGet(url).then(res => { var res3 = res console.log(res1, res2, res3); // todo 業(yè)務(wù) }).catch(err => { console.log(err) }) }).catch(err => { console.log(err) }) }).catch(err => { console.log(err) })async/await
借助 aysnc/await 解決回調(diào)地獄的問題,實(shí)現(xiàn)同步風(fēng)格的異步邏輯,這里希望大家能理解透2 & 3兩條總結(jié):
aysnc 返回的也是一個(gè) Promise 對(duì)象。
如果返回了return 標(biāo)量 或 throw Error 則返回 {PromiseStatus: resolved/rejected} 的 Promise對(duì)象。
如果遇到了await裝飾的Promise,則返回 {PromiseStatus: pending} 的 Promise。并等待此Promise的執(zhí)行結(jié)果:如果Promise觸發(fā)了resolve則獲取結(jié)果并繼續(xù)向下執(zhí)行;如果Promise觸發(fā)了reject則拋出一個(gè)異常。所以我們?cè)谑褂脮r(shí)應(yīng)將代碼使用try...catch封裝。
await 關(guān)鍵字只能在 async內(nèi)使用,await主要意圖是裝飾一個(gè)以 {PromiseStatus: pending}的狀態(tài)返回的Promise對(duì)象(任何 JS 表達(dá)式都可以,但沒什么意義),并等待其后續(xù)的resolved/rejected狀態(tài)更新,從而決定是獲得結(jié)果并繼續(xù)向下執(zhí)行,還是終止并拋出異常。
var url = window.location.href async function getUrls(url1, url2, url3) { try { // req1 success or throw error (promise reject) let res1 = await asyncHttpGet(url1); // req2 success or throw error (promise reject) let res2 = await asyncHttpGet(url2); // req3 success or throw error (promise reject) let res3 = await asyncHttpGet(url3); // 三個(gè)異步請(qǐng)求都成功 獲取最終結(jié)果 return [res1, res2, res3].join(" ") } catch(err) { // 出現(xiàn)錯(cuò)誤,做一些處理 console.log(err) throw err } } // 如此 3 個(gè) Promise 請(qǐng)求在 async/await 的封裝下變成了一個(gè)同步書寫風(fēng)格的異步請(qǐng)求 getUrls(url, url, url).then(res => { console.log(res) // todo 業(yè)務(wù) }).catch(err => { console.log(err) }) console.log("request has been sended, and waiting for res")
async 返回的是 Promise對(duì)象,所以我們還可以繼續(xù)使用 asyncawait封裝異步到同步風(fēng)格。
async function getUrlsMore(url1, url2) { try { let getUrls1 = await getUrls(url1, url1, url1) let getUrls2 = await getUrls(url2, url2, url2) // Promise resolve return [getUrls1, getUrls2].join(" ") } catch (err) { // Promise reject throw err } } getUrlsMore(url, url).then(res => { console.log(res) }).catch(err => { console.log(err) })async/await 和 Promise 的關(guān)系
async/await 和 Promise 的關(guān)系非常的巧妙,await必須在async內(nèi)使用,并裝飾一個(gè)Promise對(duì)象,async返回的也是一個(gè)Promise對(duì)象。
async/await中的return/throw會(huì)代理自己返回的Promise的resolve/reject,而一個(gè)Promise的resolve/reject會(huì)使得await得到返回值或拋出異常。
如果方法內(nèi)無await節(jié)點(diǎn)
return 一個(gè)字面量則會(huì)得到一個(gè){PromiseStatus: resolved}的Promise。
throw 一個(gè)Error則會(huì)得到一個(gè){PromiseStatus: rejected}的Promise。
如果方法內(nèi)有await節(jié)點(diǎn)
async會(huì)返回一個(gè){PromiseStatus: pending}的Promise(發(fā)生切換,異步等待Promise的執(zhí)行結(jié)果)。
Promise的resolve會(huì)使得await的代碼節(jié)點(diǎn)獲得相應(yīng)的返回結(jié)果,并繼續(xù)向下執(zhí)行。
Promise的reject 會(huì)使得await的代碼節(jié)點(diǎn)自動(dòng)拋出相應(yīng)的異常,終止向下繼續(xù)執(zhí)行。
示例:
方法內(nèi)無await節(jié)點(diǎn)// 沒有 await 修飾的 Promise async function foo() { if (Math.ceil(Math.random() * 10) > 5) { // {PromiseStatus: resolved} return "hello world" } else { // {PromiseStatus: rejected} throw new Error("something wrong!") } } var fooPromise = foo() console.log(fooPromise) fooPromise.then(res => { console.log(res) }).catch(err => { console.log(err) })
resolved
rejected
注意Promise內(nèi)的resolve/reject對(duì) await節(jié)點(diǎn)的作用。
async function bar() { try { // await 返回 {PromiseStatus: pending} let res = await new Promise((resolve, reject) => { setTimeout(() => { if (Math.ceil(Math.random() * 10) > 5) { // await 獲得結(jié)果并繼續(xù)執(zhí)行 resolve("success") } else { // await 中斷執(zhí)行并拋出異常 reject("failed") } }, 2000) }) // resolve {PromiseStatus: resolved} return res } catch (err) { // reject {PromiseStatus: rejected} throw err } } var barPromise = bar() // 查看 barPromise 的 PromiseStatus console.log(barPromise) barPromise.then(res => { console.log(res) }).catch(err => { console.log(err) })await配合fetch的實(shí)例
then/catch返回的也是Promise對(duì)象,在then/catch內(nèi)使用return/throw來決定返回的Promise是resolved/rejected。
// 沒有 await 修飾的 Promise async function bar() { try { // await 返回 {PromiseStatus: pending} let res1 = await fetch(window.location.href).then(res => { if (200 == res.status) { // Promise resolve return "request success" } else { // goto catch throw "request failed" + res.status } }).catch(err => { // Promise reject throw err }) let res2 = await fetch(window.location.href).then(res => { if (200 == res.status) { // Promise resolve return "request success" } else { // goto catch throw "request failed" + res.status } }).catch(err => { // Promise reject throw err }) let res3 = await fetch(window.location.href).then(res => { if (200 == res.status) { // Promise resolve return "request success" } else { // goto catch throw "request failed" + res.status } }).catch(err => { // Promise reject throw err }) // 三個(gè)請(qǐng)求都成功 則返回相應(yīng)的數(shù)據(jù) Promise resolved return [res1, res2, res3].join(" ") } catch (err) { // Promise rejected throw err } } var barPromise = bar() // 查看 barPromise 的 PromiseStatus console.log(barPromise) // Promise reject 拋出異常 需要使用 catch 捕捉 barPromise.then(res => { console.log(res) }).catch(err => { console.log(err) })
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/110298.html
摘要:但是中的這種情況與抽象反應(yīng)器模式如何描述完全不同。在處理一個(gè)階段之后并且在移到下一個(gè)隊(duì)列之前,事件循環(huán)將處理兩個(gè)中間隊(duì)列,直到中間隊(duì)列中沒有剩余的項(xiàng)目。如果沒有任務(wù)則循環(huán)退出,每一次隊(duì)列處理都被視為事件循環(huán)的一個(gè)階段。 Promise && async/await的理解和用法 為什么需要promise(承諾)這個(gè)東西 在之前我們處理異步函數(shù)都是用回調(diào)這個(gè)方法,回調(diào)嵌套的時(shí)候會(huì)發(fā)現(xiàn) 閱讀...
摘要:最近項(xiàng)目中用的比較多,所以特地去了解,模仿一下實(shí)現(xiàn)先來看看使用的方法通過是通過使用生成器配合方法模擬的一個(gè)同步操作,這個(gè)技術(shù)有效的避免了傳統(tǒng)回調(diào)和形成的回調(diào)地獄。 最近項(xiàng)目中 asyn & await 用的比較多,所以特地去了解,模仿一下實(shí)現(xiàn)~ 先來看看 使用 async & await 的方法 async function d () { try { const a = a...
摘要:的出現(xiàn),讓我們可以走出回調(diào)地獄,著實(shí)驚艷。我已經(jīng)開始使用里的和關(guān)鍵字來簡(jiǎn)化的處理。異步任務(wù)在這個(gè)例子是執(zhí)行之后,一直在執(zhí)行完成才繼續(xù)下一個(gè)任務(wù)并沒有產(chǎn)生阻塞。最后這個(gè)函數(shù)處理了返回值并且返回了一個(gè)對(duì)象。依然很棒,但和使得它可維護(hù)性更好。 JavaScript Promises的出現(xiàn),讓我們可以走出回調(diào)地獄,著實(shí)驚艷。Promises 允許我們更好的引入和處理異步任務(wù),雖然如此,但引入好...
摘要:但是提出標(biāo)準(zhǔn),允許腳本創(chuàng)建多個(gè)線程,但是子線程完全受主線程控制。只是將事件插入了任務(wù)隊(duì)列,必須等到當(dāng)前代碼執(zhí)行棧執(zhí)行完,主線程才會(huì)去執(zhí)行它指定的回調(diào)函數(shù)。之后全局上下文進(jìn)入函數(shù)調(diào)用棧。 setTimeout 一、setTimeout 初現(xiàn) 定義:setTimeout() 方法用于在指定的毫秒數(shù)后調(diào)用函數(shù)或計(jì)算表達(dá)式。 語(yǔ)法: setTimeout(code, millisec...
摘要:前文該系列下的前幾篇文章分別對(duì)不同的幾種異步方案原理進(jìn)行解析,本文將介紹一些實(shí)際場(chǎng)景和一些常見的面試題。流程調(diào)度里比較常見的一種錯(cuò)誤是看似串行的寫法,可以感受一下這個(gè)例子判斷以下幾種寫法的輸出結(jié)果辨別輸出順序這類題目一般出現(xiàn)在面試題里。 前文 該系列下的前幾篇文章分別對(duì)不同的幾種異步方案原理進(jìn)行解析,本文將介紹一些實(shí)際場(chǎng)景和一些常見的面試題。(積累不太夠,后面想到再補(bǔ)) 正文 流程調(diào)度...
閱讀 2283·2021-09-30 09:47
閱讀 1059·2021-08-27 13:01
閱讀 3011·2019-08-30 15:54
閱讀 3747·2019-08-30 15:53
閱讀 891·2019-08-29 14:07
閱讀 781·2019-08-28 18:16
閱讀 879·2019-08-26 18:37
閱讀 1473·2019-08-26 13:27