成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

前端er,你真的會(huì)用 async 嗎?

Jaden / 1918人閱讀

摘要:異步函數(shù)是值通過事件循環(huán)異步執(zhí)行的函數(shù),它會(huì)通過一個(gè)隱式的返回其結(jié)果。

async 異步函數(shù) 不完全使用攻略 前言

現(xiàn)在已經(jīng)到 8012 年的尾聲了,前端各方面的技術(shù)發(fā)展也層出不窮,VueConf TO 2018 大會(huì) 也發(fā)布了 Vue 3.0的計(jì)劃。而在我們(我)的日常中也經(jīng)常用 Vue 來編寫一些項(xiàng)目。那么,就少不了 ES6 的登場了。那么話說回來,你真的會(huì)用 ES6 的 async 異步函數(shù)嗎?

1、async 介紹

先上 MDN 介紹:https://developer.mozilla.org...

async function 用于聲明 一個(gè) 返回 AsyncFunction 對象的異步函數(shù)。異步函數(shù)是值通過事件循環(huán)異步執(zhí)行的函數(shù),它會(huì)通過一個(gè)隱式的 Promise 返回其結(jié)果。如果你的代碼使用了異步函數(shù),它的語法和結(jié)構(gòu)更像是標(biāo)準(zhǔn)的同步函數(shù)

人工翻譯:async 關(guān)鍵字是用于表示一個(gè)函數(shù)里面有異步操作的含義。它通過返回一個(gè) Promise 對象來返回結(jié)果它的最大的特點(diǎn)是:通過 async / await 將異步的操作,但是寫法和結(jié)構(gòu)卻是和我們平時(shí)寫的(同步代碼)是一樣

2、示范
// 一般我們會(huì)把所有請求方法都定義在一個(gè)文件里,這里定義一個(gè)方法來模擬我們的日常請求
function fetch() {
    axios.get("/user?ID=12345")
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });
};
// 然后在需要它的地方調(diào)用它
async function getUserInfo() {
    const info = await fetch();

    return info;
}
getUserInfo().then(info => console.log(info));

我們可以看到,整個(gè)過程非常直觀和清晰,語句語義非常明確,整個(gè)異步操作看起來就像是同步一樣。如果看完上面的流程沒有問題的話,那我們接下來繼續(xù)深入的了解一下。

3、async Promise setTimeout(定時(shí)器) 的結(jié)合使用情況

接下來給大家演示一道題目,這道題是我當(dāng)時(shí)面某條的面試題,估計(jì)和多人也見過,這道題非常經(jīng)典而且使用場景頁非常多,研究意義非常大,那么我在這里就給大家分享一下。

求下面的輸出結(jié)果:
async function async1(){
    console.log("async1 start")
    await async2()
    console.log("async1 end")
}
async function async2(){
    console.log("async2")
}
console.log("script start")
setTimeout(function(){
    console.log("setTimeout")
},0)  
async1();
new Promise(function(resolve){
    console.log("promise1")
    resolve();
}).then(function(){
    console.log("promise2")
})
console.log("script end")

這里一共有 8 條 log 語句,先別復(fù)制到控制臺上,大家給20秒鐘的時(shí)間默念一下輸出的順序。

1..2.. .. .. 20

我先給上正確的答案:

script start
async1 start
async2
promise1
script end
promise2
async1 end
setTimeout

如果你的答案和上面的正確答案有所偏差,那么說明你對 async / await 的理解還是不夠深刻,希望你閱讀完我的這篇文章之后可以直面各種同步異步問題了(嘻嘻,這還不點(diǎn)個(gè)贊嘛)

我們再來回顧一下 MDN 對 async / await 的描述:

當(dāng)調(diào)用一個(gè) async 函數(shù)時(shí),會(huì)返回一個(gè) Promise 對象。當(dāng)這個(gè) async 函數(shù)返回一個(gè)值時(shí),Promise 的 resolve 方法會(huì)負(fù)責(zé)傳遞這個(gè)值;當(dāng) async 函數(shù)拋出異常時(shí),Promise 的 reject 方法也會(huì)傳遞這個(gè)異常值。

async 函數(shù)中可能會(huì)有 await 表達(dá)式,這會(huì)使 async 函數(shù)暫停執(zhí)行,等待 Promise 的結(jié)果出來,然后恢復(fù)async函數(shù)的執(zhí)行并返回解析值(resolved)。

async/await的用途是簡化使用 promises 異步調(diào)用的操作,并對一組 Promises執(zhí)行某些操作。正如Promises類似于結(jié)構(gòu)化回調(diào),async/await類似于組合生成器和 promises。

await

await 操作符用于等待一個(gè)Promise 對象。它只能在異步函數(shù) async function 中使用。

[return_value] = await expression;

await 表達(dá)式會(huì)暫停當(dāng)前 async function 的執(zhí)行,等待 Promise 處理完成。若 Promise 正常處理(fulfilled),其回調(diào)的resolve函數(shù)參數(shù)作為 await 表達(dá)式的值,繼續(xù)執(zhí)行 async function

若 Promise 處理異常(rejected),await 表達(dá)式會(huì)把 Promise 的異常原因拋出。

另外,如果 await 操作符后的表達(dá)式的值不是一個(gè) Promise,則返回該值本身。

其中非常重要的一句是:遇到 await 表達(dá)式時(shí),會(huì)讓 async 函數(shù) 暫停執(zhí)行,等到 await 后面的語句(Promise)狀態(tài)發(fā)生改變(resolved或者rejected)之后,再恢復(fù) async 函數(shù)的執(zhí)行(再之后 await 下面的語句),并返回解析值(Promise的值)

這么多 Promise 相關(guān)的內(nèi)容是因?yàn)閍sync / await 是建立在 Promise 的基礎(chǔ)上的呀~~

然后再來回頭看我們的題目,會(huì)發(fā)現(xiàn),有點(diǎn)不對勁啊

async1 end
promise2

那是因?yàn)檫€有一個(gè)Promise.resolve 的點(diǎn)沒有考慮,這也是我中招的點(diǎn)

4、分析過程

定義一個(gè)異步函數(shù) async1

定義一個(gè)異步函數(shù) async2

打印 ‘script start’ // *1

定義一個(gè)定時(shí)器(宏任務(wù),優(yōu)先級低于微任務(wù)),在0ms 之后輸出

執(zhí)行異步函數(shù) async1

打印 "async1 start" // *2

遇到await 表達(dá)式,執(zhí)行 await 后面的 async2

打印 "async2" // *3

返回一個(gè) Promise,跳出 async1 函數(shù)體

執(zhí)行 new Promise 里的語句

打印 ‘promise1‘ // *4

resolve() , 返回一個(gè) Promise 對象,把這個(gè) Promise 壓進(jìn)隊(duì)列里

打印 ’script end" // *5

同步棧執(zhí)行完畢

回到 async1 的函數(shù)體,async2 函數(shù)沒有返回 Promise,所以把要等async2 的值 resolve,把 Promise 壓進(jìn)隊(duì)列

執(zhí)行 new Promise 后面的 .then,打印 ’promise2‘ // *6

回到 async1 的函數(shù)體,await 返回 Promise.resolve() ,然后打印后面的 ’async1 end‘ // *7

最后執(zhí)行定時(shí)器(宏任務(wù)) setTimeout,打印 ’setTimeout‘ // *8

我對這段代碼的過程分析大致如上(如果有什么理解不對的地方請指出),這里有很關(guān)鍵而且是大家容易理解錯(cuò)誤的點(diǎn)是:很多人以為 await 會(huì)一直等待后面的表達(dá)式執(zhí)行完之后才會(huì)執(zhí)行后續(xù)代碼,實(shí)際上 await 是會(huì)先執(zhí)行后面的表達(dá)式,然后返回一個(gè)Promise,接著就跳出整個(gè) async 函數(shù)來執(zhí)行后面的代碼,也就是說執(zhí)行到 await 的時(shí)候,會(huì)有一個(gè) 讓出線程 的操作。等后面的同步站執(zhí)行完了之后,又會(huì)回到 async 函數(shù)中等待 await 表達(dá)式的返回值,如果不是一個(gè) Promise 對象,則會(huì)有一個(gè)期待它 resolve 成為一個(gè) Promise對象的過程,然后繼續(xù)執(zhí)行 async 函數(shù)后面的代碼,直到是一個(gè) Promise 對象,則把這個(gè) Promise 對象放入 Promise 隊(duì)列里。

所以說 ,’async1 end" 和‘promise2‘ 這個(gè)不注意就會(huì)出錯(cuò)的難點(diǎn)就是這樣

那么現(xiàn)在,我們是不是大致上對async / await 理解了呢,我們來改一下這道題再來看看,把 async2 改造一下

async function async1(){
    console.log("async1 start")
    await async2()
    console.log("async1 end")
}
function async2(){ // 去掉了 async 關(guān)鍵字
    console.log("async2");
}
console.log("script start")
setTimeout(function(){
    console.log("setTimeout")
},0)  
async1();
new Promise(function(resolve){
    console.log("promise1")
    resolve();
}).then(function(){
    console.log("promise2")
})
console.log("script end")

這次大家能做對了嗎~

5、日常常用示例

上面寫了那么多,只是為了方便大家對于異步函數(shù)的理解,

下面給一些我們?nèi)粘i_發(fā)中使用異步函數(shù)的例子。一般來說,我們有一個(gè)業(yè)務(wù)需要分不完成,每個(gè)步驟都是異步的,并且嚴(yán)重依賴于上一步的執(zhí)行結(jié)果,稍有不慎就會(huì)進(jìn)入回調(diào)地獄(callback hell)了,這種情況下,我們可以用 async / await 來完成

// 比如在這里場景,我們提交數(shù)據(jù)的時(shí)候先判定用戶是否有這個(gè)權(quán)限,然后再進(jìn)行下一步動(dòng)作
async function submitData(data) {
    const res = await getAuth(); // 獲取授權(quán)狀態(tài)
    if (res....) {
        const data = await submit(data);
    }
    toast(data.message);
}

這樣就可以保證兩個(gè)操作的先后順序

或者是在 Vue 中,一些初始化的操作

async created() {
    const res = await this.init(); // 獲取列表等操作
    const list = await this.getPage(); // 分頁請求等
}

但是在使用過程中,我們會(huì)發(fā)現(xiàn)剛從回調(diào)地獄中解救,然后就陷入 async / await 地獄的誕生

舉一個(gè)例子:

async created() {
    const userInfo = await this.getUserInfo(); // 獲取用戶數(shù)據(jù)
    const list = await this.getNewsList(); // 獲取文章數(shù)據(jù)
}

表面上看,這段語法是正確的,但并不是一個(gè)優(yōu)秀實(shí)現(xiàn),因?yàn)樗褍蓚€(gè)沒有先后順序的一部操作強(qiáng)行變成同步操作了,因?yàn)檫@里的代碼是一行接著一行執(zhí)行的,想一下,我們沒有必要在獲取用戶數(shù)據(jù)之后才去獲取文章數(shù)據(jù),它們的工作是可以同時(shí)進(jìn)行的

這里給出一些常用的并發(fā)執(zhí)行的實(shí)例

async created() {
    const userInfo = this.getUserInfo(); // 它們都會(huì)返回 Promise 對象
    const list = this.getNewsList();
    await userInfo;
    await list;
    // ...do something
}
// 如果有很多請求的情況下可以使用 Promise.all
async created() {
    Promise.all([this.getUserInfo(), this.getNewsList()]).then(()=> {
        // ...do something
    });
}
5、圖例

6、小結(jié)

1、異步的終極解決方案

2、看起來像同步的異步操作

3、便捷的捕獲錯(cuò)誤和調(diào)試

4、支持并發(fā)執(zhí)行

5、要知道避免 async / await 地獄

7、寫在最后

好了,關(guān)于async 異步函數(shù)的不完全指南就說到這里了,上面所提及的內(nèi)容,可能也就比較淺顯的內(nèi)容。而且有時(shí)候,建議大家熟練使用它,在日常開發(fā)中多使用多總結(jié)才會(huì)有沉淀的效果,都是要靠自己多練,才能熟悉使用,熟能生巧!
最后,如果大家覺得我有哪里寫錯(cuò)了,寫得不好,有其它什么建議(夸獎(jiǎng)),非常歡迎大家補(bǔ)充。希望能讓大家交流意見,相互學(xué)習(xí),一起進(jìn)步!
我是一名 19 的應(yīng)屆新人,以上就是今天的分享,新手上路中,后續(xù)不定期周更(或者是月更哈哈),我會(huì)努力讓自己變得更優(yōu)秀、寫出更好的文章,文章中有不對之處,煩請各位大神斧正。如果你覺得這篇文章對你有所幫助,請記得點(diǎn)贊或者品論留言哦~。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/99662.html

相關(guān)文章

  • 真的會(huì)用 Babel ?

    摘要:安裝然后在的配置文件加入入口文件引入這樣就可以啦,還是可以減少很多代碼量的。是參數(shù),等同于執(zhí)行正常。這個(gè)包很簡單,就是引用了和,然后生產(chǎn)環(huán)境把它們編譯到目錄下,做了映射,供使用。 引入 這個(gè)問題是對自己的發(fā)問,但我相信會(huì)有很多跟我一樣的同學(xué)。對于 babel 的使用,近半年來一直停留在與 webpack 結(jié)合使用,以及在瀏覽器開發(fā)環(huán)境下。導(dǎo)致很多 babel 的包,我都不清楚他們是干嘛...

    mochixuan 評論0 收藏0
  • 2019前端工程師自檢清單與思考

    摘要:前端工程師自檢清單對于,掌握其語法和特性是最基本的,但是這些只是應(yīng)用能力,最終仍舊考量仍然是計(jì)算機(jī)體系的理論知識,所以數(shù)據(jù)結(jié)構(gòu),算法,軟件工程,設(shè)計(jì)模式等基礎(chǔ)知識對前端工程師同樣重要,這些知識的理解程度,可以決定你在前端工程師這條路上能走多 2019前端工程師自檢清單 對于JavaScript,掌握其語法和特性是最基本的,但是這些只是應(yīng)用能力,最終仍舊考量仍然是計(jì)算機(jī)體系的理論知識,所...

    Honwhy 評論0 收藏0
  • 不知道的h5

    摘要:目前,常用的模塊規(guī)范主要有兩種和。攔截全局請求一直接引入腳本攔截需要的回調(diào)或函數(shù)。深刻知道一個(gè)良好的命名規(guī)范的重要性,同時(shí)在項(xiàng)目中也會(huì)遇到一些命名的瓶頸。 基于 Three.js 的超快的 3D 開發(fā)框架:Whitestorm.js Whitestorm.js 是一款基于 Three.js 超快的 Web 應(yīng)用 3D 開發(fā)框架。它為普通的 Three.js 任務(wù)提供封裝、使搭建環(huán)境、...

    IntMain 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<