自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

async / await:更好的異步解決方案

開(kāi)發(fā) 前端
在實(shí)際開(kāi)發(fā)中總會(huì)遇到許多異步的問(wèn)題,最常見(jiàn)的場(chǎng)景接口請(qǐng)求之后一定要等一段時(shí)間才能得到結(jié)果,如果遇到多個(gè)接口前后依賴(lài),那么問(wèn)題就變得復(fù)雜。大家都一直在嘗試使用更好的方案來(lái)解決這些問(wèn)題。

[[198841]]

在實(shí)際開(kāi)發(fā)中總會(huì)遇到許多異步的問(wèn)題,最常見(jiàn)的場(chǎng)景接口請(qǐng)求之后一定要等一段時(shí)間才能得到結(jié)果,如果遇到多個(gè)接口前后依賴(lài),那么問(wèn)題就變得復(fù)雜。大家都一直在嘗試使用更好的方案來(lái)解決這些問(wèn)題。最開(kāi)始只能利用回調(diào)函數(shù),后來(lái)開(kāi)始有人使用Promise的思維來(lái)搞定。到ES6中開(kāi)始支持原生的Promise,引入Generator函數(shù)。

直到ES7,有了async/await。

這是一個(gè)用同步的思維來(lái)解決異步問(wèn)題的方案。

我想很多人可能還不太分得清同步與異步的區(qū)別。如果你已經(jīng)徹底了解了事件循環(huán),那么想必對(duì)異步的概念應(yīng)該非常了解。當(dāng)我們發(fā)出了請(qǐng)求,并不會(huì)等待響應(yīng)結(jié)果,而是會(huì)繼續(xù)執(zhí)行后面的代碼,響應(yīng)結(jié)果的處理在之后的事件循環(huán)中解決。那么同步的意思,就是等結(jié)果出來(lái)之后,代碼才會(huì)繼續(xù)往下執(zhí)行。

我們可以用一個(gè)兩人問(wèn)答的場(chǎng)景來(lái)比喻異步與同步。A向B問(wèn)了一個(gè)問(wèn)題之后,不等待B的回答,接著問(wèn)下一個(gè)問(wèn)題,這是異步。A向B問(wèn)了一個(gè)問(wèn)題之后,然后就笑呵呵的等著B(niǎo)回答,B回答了之后他才會(huì)接著問(wèn)下一個(gè)問(wèn)題。

那么我們先記住這個(gè)特點(diǎn),async/await使用同步的思維,來(lái)解決異步的問(wèn)題。在繼續(xù)講解它的語(yǔ)法與使用之前,我們先介紹一下如何在我們的開(kāi)發(fā)環(huán)境中支持該語(yǔ)法。

如果你已經(jīng)知道如何配置,可跳過(guò)

一、如何在自己的開(kāi)發(fā)環(huán)境中支持async/await語(yǔ)法

這里主要介紹兩種方式。

1. webpack中支持該語(yǔ)法

首先在當(dāng)前項(xiàng)目中使用npm下載babel-loader。

  1. > npm install babel-loader --save-dev 

然后在配置文件webpack.confing.dev.js中配置,在module.exports.module.rules中添加如下配置元素即可。

  1.  
  2.     test: /\.(js|jsx)$/, 
  3.  
  4.     include: paths.appSrc, 
  5.  
  6.     loader: require.resolve('babel-loader'), 
  7.  
  8.     options: { 
  9.  
  10.       cacheDirectory: true
  11.  
  12.     }, 
  13.  
  14.   },  

如果你使用***版本的create-react-app或者vue-cli來(lái)構(gòu)建你的代碼,那么它們應(yīng)該已經(jīng)支持了該配置。

2. gulp中支持該語(yǔ)法

首先安裝gulp插件

  1. > npm install gulp-babel --save-dev 

然后編寫(xiě)任務(wù)

  1. var gulp = require('gulp'); 
  2.  
  3. var babel = require('gulp-babel'); 
  4.  
  5.   
  6.  
  7. gulp.task('babel'function() { 
  8.  
  9.   return gulp.src('src/app.js'
  10.  
  11.     .pipe(babel()) 
  12.  
  13.     .pipe(gulp.dest('dist')); 
  14.  
  15. });  

二、如何使用

async函數(shù)是Generator的一個(gè)語(yǔ)法糖。如果你不知道Generator是什么函數(shù)也沒(méi)有關(guān)系,我們只需要知道async函數(shù)實(shí)際上返回的是一個(gè)Promise對(duì)象即可。

  1. async function fn() { 
  2.  
  3.     return 30; 
  4.  
  5.  
  6.   
  7.  
  8. // 或者 
  9.  
  10. const fn = async () => { 
  11.  
  12.     return 30; 
  13.  
  14.  

在聲明函數(shù)時(shí),前面加上關(guān)鍵字async,這就是async的用法。當(dāng)我們用console.log打印出上面聲明的函數(shù)fn,我們可以看到如下結(jié)果:

  1. console.log(fn()); 
  2.  
  3.   
  4.  
  5.     // result 
  6.  
  7.     Promise = { 
  8.  
  9.         __proto__: Promise, 
  10.  
  11.         [[PromiseStatus]]: "resolved"
  12.  
  13.         [[PromiseValue]]: 30 
  14.  
  15.     }  

很顯然,fn的運(yùn)行結(jié)果其實(shí)就是一個(gè)Promise對(duì)象。因此我們也可以使用then來(lái)處理后續(xù)邏輯。

  1. fn().then(res => { 
  2.  
  3.     console.log(res);  // 30 
  4.  
  5. })  

await的含義為等待。意思就是代碼需要等待await后面的函數(shù)運(yùn)行完并且有了返回結(jié)果之后,才繼續(xù)執(zhí)行下面的代碼。這正是同步的效果。

但是我們需要注意的是,await關(guān)鍵字只能在async函數(shù)中使用。并且await后面的函數(shù)運(yùn)行后必須返回一個(gè)Promise對(duì)象才能實(shí)現(xiàn)同步的效果。

當(dāng)我們使用一個(gè)變量去接收await的返回值時(shí),該返回值為Promise中resolve出來(lái)的值。

  1. // 定義一個(gè)返回Promise對(duì)象的函數(shù) 
  2.  
  3. function fn() { 
  4.  
  5.     return new Promise((resolve, reject) => { 
  6.  
  7.         setTimeout(() => { 
  8.  
  9.             resolve(30); 
  10.  
  11.         }, 1000); 
  12.  
  13.     }) 
  14.  
  15.  
  16.   
  17.  
  18. // 然后利用async/await來(lái)完成代碼 
  19.  
  20. const foo = async () => { 
  21.  
  22.     const t = await fn(); 
  23.  
  24.     console.log(t); 
  25.  
  26.     console.log('next code'); 
  27.  
  28.  
  29.   
  30.  
  31. foo(); 
  32.  
  33.   
  34.  
  35. // result: 
  36.  
  37. // 30 
  38.  
  39. // next code  

運(yùn)行這個(gè)例子我們可以看出,當(dāng)在async函數(shù)中,運(yùn)行遇到await時(shí),就會(huì)等待await后面的函數(shù)運(yùn)行完畢,而不會(huì)直接執(zhí)行next code。

如果我們直接使用then方法的話(huà),想要達(dá)到同樣的結(jié)果,就不得不把后續(xù)的邏輯寫(xiě)在then方法中。

  1. const foo = () => { 
  2.  
  3.     return fn().then(t => { 
  4.  
  5.         console.log(t); 
  6.  
  7.         console.log('next code');     
  8.  
  9.     }) 
  10.  
  11.  
  12.   
  13.  
  14. foo();  

很顯然如果使用async/await的話(huà),代碼結(jié)構(gòu)會(huì)更加簡(jiǎn)潔,邏輯也更加清晰。

異常處理

在Promise中,我們知道是通過(guò)catch的方式來(lái)捕獲異常。而當(dāng)我們使用async時(shí),則通過(guò)try/catch來(lái)捕獲異常。

  1. function fn() { 
  2.  
  3.     return new Promise((resolve, reject) => { 
  4.  
  5.         setTimeout(() => { 
  6.  
  7.             reject('some error.'); 
  8.  
  9.         }, 1000); 
  10.  
  11.     }) 
  12.  
  13.  
  14.   
  15.  
  16. const foo = async () => { 
  17.  
  18.     try { 
  19.  
  20.         await fn(); 
  21.  
  22.     } catch (e) { 
  23.  
  24.         console.log(e);  // some error 
  25.  
  26.     } 
  27.  
  28.  
  29.   
  30.  
  31. foo();  

如果有多個(gè)await函數(shù),那么只會(huì)返回***個(gè)捕獲到的異常。

  1. function fn1() { 
  2.  
  3.     return new Promise((resolve, reject) => { 
  4.  
  5.         setTimeout(() => { 
  6.  
  7.             reject('some error fn1.'); 
  8.  
  9.         }, 1000); 
  10.  
  11.     }) 
  12.  
  13.  
  14. function fn2() { 
  15.  
  16.     return new Promise((resolve, reject) => { 
  17.  
  18.         setTimeout(() => { 
  19.  
  20.             reject('some error fn2.'); 
  21.  
  22.         }, 1000); 
  23.  
  24.     }) 
  25.  
  26.  
  27.   
  28.  
  29. const foo = async () => { 
  30.  
  31.     try { 
  32.  
  33.         await fn1(); 
  34.  
  35.         await fn2(); 
  36.  
  37.     } catch (e) { 
  38.  
  39.         console.log(e);  // some error fn1. 
  40.  
  41.     } 
  42.  
  43.  
  44.   
  45.  
  46. foo();  

實(shí)踐

在實(shí)踐中我們遇到異步場(chǎng)景最多的就是接口請(qǐng)求,那么這里就以jquery中的$.get為例簡(jiǎn)單展示一下如何配合async/await來(lái)解決這個(gè)場(chǎng)景。

  1. // 先定義接口請(qǐng)求的方法,由于jquery封裝的幾個(gè)請(qǐng)求方法都是返回Promise實(shí)例,因此可以直接使用await函數(shù)實(shí)現(xiàn)同步 
  2.  
  3. const getUserInfo = () => $.get('xxxx/api/xx'); 
  4.  
  5.   
  6.  
  7. const clickHandler = async () => { 
  8.  
  9.     try { 
  10.  
  11.         const resp = await getUserInfo(); 
  12.  
  13.         // resp為接口返回內(nèi)容,接下來(lái)利用它來(lái)處理對(duì)應(yīng)的邏輯 
  14.  
  15.         console.log(resp); 
  16.  
  17.   
  18.  
  19.         // do something 
  20.  
  21.     } catch (e) { 
  22.  
  23.         // 處理錯(cuò)誤邏輯 
  24.  
  25.     } 
  26.  
  27.  

為了保證邏輯的完整性,在實(shí)踐中try/catch必不可少??傊?,不處理錯(cuò)誤邏輯的程序員不是好程序員。

與Promise相比,個(gè)人認(rèn)為async/await有一定的簡(jiǎn)潔性,但也并非就比Promise有絕對(duì)的優(yōu)勢(shì),因此只能算是提供了另外一種稍好的方式,至于大家學(xué)習(xí)之后選擇哪種方式來(lái)解決自己的問(wèn)題,這僅僅只是你的個(gè)人喜好問(wèn)題。 

責(zé)任編輯:龐桂玉 來(lái)源: 前端大全
相關(guān)推薦

2021-06-28 08:10:59

JavaScript異步編程

2024-12-23 08:00:45

2014-07-15 10:08:42

異步編程In .NET

2021-09-01 10:35:19

asyncawaitVue

2023-11-03 14:32:38

2023-04-14 08:10:59

asyncawait

2014-07-15 10:31:07

asyncawait

2016-11-22 11:08:34

asyncjavascript

2024-06-25 08:33:48

2018-12-19 18:40:28

JavaScriptes6 前端

2022-07-11 10:32:35

Vue3await響應(yīng)式

2023-10-08 10:21:11

JavaScriptAsync

2021-02-09 09:53:11

C#多線(xiàn)程異步

2024-11-13 01:00:18

asyncawait?編程

2023-05-08 11:49:05

asyncawait場(chǎng)景

2018-06-14 14:25:42

2013-08-26 09:18:52

2013-05-16 10:33:11

C#C# 5.0Async

2024-10-14 08:29:14

異步編程任務(wù)

2012-07-22 15:59:42

Silverlight
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)