摘要:大家都一直在嘗試使用更好的方案來解決這些問題。這是一個用同步的思維來解決異步問題的方案。當(dāng)我們發(fā)出了請求,并不會等待響應(yīng)結(jié)果,而是會繼續(xù)執(zhí)行后面的代碼,響應(yīng)結(jié)果的處理在之后的事件循環(huán)中解決。我們可以用一個兩人問答的場景來比喻異步與同步。
在實際開發(fā)中總會遇到許多異步的問題,最常見的場景便是接口請求之后一定要等一段時間才能得到結(jié)果,如果遇到多個接口前后依賴,那么問題就變得復(fù)雜。大家都一直在嘗試使用更好的方案來解決這些問題。最開始只能利用回調(diào)函數(shù),后來開始有人使用Promise的思維來搞定。到ES6中開始支持原生的Promise,引入Generator函數(shù)。
直到ES7,有了async/await。
這是一個用同步的思維來解決異步問題的方案。
我想很多人可能還不太分得清同步與異步的區(qū)別。如果你已經(jīng)徹底了解了事件循環(huán),那么想必對異步的概念應(yīng)該非常了解。當(dāng)我們發(fā)出了請求,并不會等待響應(yīng)結(jié)果,而是會繼續(xù)執(zhí)行后面的代碼,響應(yīng)結(jié)果的處理在之后的事件循環(huán)中解決。那么同步的意思,就是等結(jié)果出來之后,代碼才會繼續(xù)往下執(zhí)行。
我們可以用一個兩人問答的場景來比喻異步與同步。A向B問了一個問題之后,不等待B的回答,接著問下一個問題,這是異步。A向B問了一個問題之后,然后就笑呵呵的等著B回答,B回答了之后他才會接著問下一個問題,這是同步。
那么我們先記住這個特點,async/await使用同步的思維,來解決異步的問題。
在繼續(xù)分析它的語法與使用之前,我們先介紹一下如何在我們的開發(fā)環(huán)境中支持該語法。
如果你已經(jīng)知道如何配置,可跳過一、如何在自己的開發(fā)環(huán)境中支持async/await語法
這里主要介紹兩種方式。
1. webpack中支持該語法首先在當(dāng)前項目中使用npm下載babel-loader。
> npm install babel-loader --save-dev
然后在配置文件webpack.confing.dev.js中配置,在module.exports.module.rules中添加如下配置元素即可。
{ test: /.(js|jsx)$/, include: paths.appSrc, loader: require.resolve("babel-loader"), options: { cacheDirectory: true, }, },
如果你使用最新版本的create-react-app或者vue-cli來構(gòu)建你的代碼,那么它們應(yīng)該已經(jīng)支持了該配置。
首先安裝gulp插件
> npm install gulp-babel --save-dev
然后編寫任務(wù)
var gulp = require("gulp"); var babel = require("gulp-babel"); gulp.task("babel", function() { return gulp.src("src/app.js") .pipe(babel()) .pipe(gulp.dest("dist")); });二、如何使用
async函數(shù)是Generator的一個語法糖。如果你不知道Generator是什么函數(shù)也沒有關(guān)系,我們只需要知道async函數(shù)實際上返回的是一個Promise對象即可。
async function fn() { return 30; } // 或者 const fn = async () => { return 30; }
在聲明函數(shù)時,前面加上關(guān)鍵字async,這就是async的用法。當(dāng)我們用console.log打印出上面聲明的函數(shù)fn,我們可以看到如下結(jié)果:
console.log(fn()); // result Promise = { __proto__: Promise, [[PromiseStatus]]: "resolved", [[PromiseValue]]: 30 }
很顯然,fn的運(yùn)行結(jié)果其實就是一個Promise對象。因此我們也可以使用then來處理后續(xù)邏輯。
fn().then(res => { console.log(res); // 30 })
await的含義為等待。意思就是代碼需要等待await后面的函數(shù)運(yùn)行完并且有了返回結(jié)果之后,才繼續(xù)執(zhí)行下面的代碼。這正是同步的效果。
但是我們需要注意的是,await關(guān)鍵字只能在async函數(shù)中使用。并且await后面的函數(shù)運(yùn)行后必須返回一個Promise對象才能實現(xiàn)同步的效果。
當(dāng)我們使用一個變量去接收await的返回值時,該返回值為Promise中resolve出來的值(也就是PromiseValue)。
// 定義一個返回Promise對象的函數(shù) function fn() { return new Promise((resolve, reject) => { setTimeout(() => { resolve(30); }, 1000); }) } // 然后利用async/await來完成代碼 const foo = async () => { const t = await fn(); console.log(t); console.log("next code"); } foo(); // result: // 30 // next code
運(yùn)行這個例子我們可以看出,當(dāng)在async函數(shù)中,運(yùn)行遇到await時,就會等待await后面的函數(shù)運(yùn)行完畢,而不會直接執(zhí)行next code。
如果我們直接使用then方法的話,想要達(dá)到同樣的結(jié)果,就不得不把后續(xù)的邏輯寫在then方法中。
const foo = () => { return fn().then(t => { console.log(t); console.log("next code"); }) } foo();
很顯然如果使用async/await的話,代碼結(jié)構(gòu)會更加簡潔,邏輯也更加清晰。
在Promise中,我們知道是通過catch的方式來捕獲異常。而當(dāng)我們使用async時,則通過try/catch來捕獲異常。
function fn() { return new Promise((resolve, reject) => { setTimeout(() => { reject("some error."); }, 1000); }) } const foo = async () => { try { await fn(); } catch (e) { console.log(e); // some error } } foo();
如果有多個await函數(shù),那么只會返回第一個捕獲到的異常。
function fn1() { return new Promise((resolve, reject) => { setTimeout(() => { reject("some error fn1."); }, 1000); }) } function fn2() { return new Promise((resolve, reject) => { setTimeout(() => { reject("some error fn2."); }, 1000); }) } const foo = async () => { try { await fn1(); await fn2(); } catch (e) { console.log(e); // some error fn1. } } foo();
在實踐中我們遇到異步場景最多的就是接口請求,那么這里就以jquery中的$.get為例簡單展示一下如何配合async/await來解決這個場景。
// 先定義接口請求的方法,由于jquery封裝的幾個請求方法都是返回Promise實例,因此可以直接使用await函數(shù)實現(xiàn)同步 const getUserInfo = () => $.get("xxxx/api/xx"); const clickHandler = async () => { try { const resp = await getUserInfo(); // resp為接口返回內(nèi)容,接下來利用它來處理對應(yīng)的邏輯 console.log(resp); // do something } catch (e) { // 處理錯誤邏輯 } }
為了保證邏輯的完整性,在實踐中try/catch必不可少。總之,不處理錯誤邏輯的程序員不是好程序員。
與Promise相比,個人認(rèn)為async/await有一定的簡潔性,但也并非就比Promise有絕對的優(yōu)勢,因此只能算是提供了另外一種同樣很棒的方式,至于大家學(xué)習(xí)之后選擇哪種方式來解決自己的問題,我認(rèn)為這僅僅只是個人的喜好問題。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/92095.html
摘要:一個簡單的轉(zhuǎn)換為的例子我們調(diào)用函數(shù)返回一個的實例,在實例化的過程中進(jìn)行文件的讀取,當(dāng)文件讀取的回調(diào)觸發(fā)式,進(jìn)行狀態(tài)的變更,或者狀態(tài)的變更我們使用來監(jiān)聽,第一個回調(diào)為的處理,第二個回調(diào)為的處理。 2018年已經(jīng)到了5月份,node的4.x版本也已經(jīng)停止了維護(hù) 我司的某個服務(wù)也已經(jīng)切到了8.x,目前正在做koa2.x的遷移 將之前的generator全部替換為async 但是,在替換...
摘要:的出現(xiàn),讓我們可以走出回調(diào)地獄,著實驚艷。我已經(jīng)開始使用里的和關(guān)鍵字來簡化的處理。異步任務(wù)在這個例子是執(zhí)行之后,一直在執(zhí)行完成才繼續(xù)下一個任務(wù)并沒有產(chǎn)生阻塞。最后這個函數(shù)處理了返回值并且返回了一個對象。依然很棒,但和使得它可維護(hù)性更好。 JavaScript Promises的出現(xiàn),讓我們可以走出回調(diào)地獄,著實驚艷。Promises 允許我們更好的引入和處理異步任務(wù),雖然如此,但引入好...
摘要:如果你還沒讀過上篇上篇和中篇并無依賴關(guān)系,您可以讀過本文之后再閱讀上篇,可戳面試篇寒冬求職季之你必須要懂的原生上小姐姐花了近百個小時才完成這篇文章,篇幅較長,希望大家閱讀時多花點耐心,力求真正的掌握相關(guān)知識點。 互聯(lián)網(wǎng)寒冬之際,各大公司都縮減了HC,甚至是采取了裁員措施,在這樣的大環(huán)境之下,想要獲得一份更好的工作,必然需要付出更多的努力。 一年前,也許你搞清楚閉包,this,原型鏈,就能獲得...
摘要:的翻譯文檔由的維護(hù)很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:取而代之,利用事件循環(huán)體系,使用了一種類似語法的工作方式一旦非阻塞的異步操作完成之后,就可以讓開發(fā)者分配的回調(diào)函數(shù)被觸發(fā)。第一個嘗試嵌套的回調(diào)函數(shù)下面是使用嵌套的回調(diào)函數(shù)的實現(xiàn)方法這可能對于任何使用者來說再熟悉不過了。 寫在文章前 這篇文章翻譯自 ASYNC/AWAIT WILL MAKE YOUR CODE SIMPLER,這是一篇寫于2017年八月的文章,并由某專欄提名為17年十大...
閱讀 1850·2021-11-11 16:55
閱讀 1462·2019-08-30 15:54
閱讀 784·2019-08-29 15:34
閱讀 2263·2019-08-29 13:11
閱讀 2919·2019-08-26 13:28
閱讀 1886·2019-08-26 10:49
閱讀 1003·2019-08-26 10:40
閱讀 2564·2019-08-23 18:21