国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

前端er,你真的會用 async 嗎?

Jaden / 1909人閱讀

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

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

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

1、async 介紹

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

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

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

2、示范
// 一般我們會把所有請求方法都定義在一個文件里,這里定義一個方法來模擬我們的日常請求
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));

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

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

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

求下面的輸出結果:
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 語句,先別復制到控制臺上,大家給20秒鐘的時間默念一下輸出的順序。

1..2.. .. .. 20

我先給上正確的答案:

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

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

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

當調(diào)用一個 async 函數(shù)時,會返回一個 Promise 對象。當這個 async 函數(shù)返回一個值時,Promise 的 resolve 方法會負責傳遞這個值;當 async 函數(shù)拋出異常時,Promise 的 reject 方法也會傳遞這個異常值。

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

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

await

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

[return_value] = await expression;

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

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

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

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

這么多 Promise 相關的內(nèi)容是因為async / await 是建立在 Promise 的基礎上的呀~~

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

async1 end
promise2

那是因為還有一個Promise.resolve 的點沒有考慮,這也是我中招的點

4、分析過程

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

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

打印 ‘script start’ // *1

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

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

打印 "async1 start" // *2

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

打印 "async2" // *3

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

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

打印 ‘promise1‘ // *4

resolve() , 返回一個 Promise 對象,把這個 Promise 壓進隊列里

打印 ’script end" // *5

同步棧執(zhí)行完畢

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

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

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

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

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

所以說 ,’async1 end" 和‘promise2‘ 這個不注意就會出錯的難點就是這樣

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

async function async1(){
    console.log("async1 start")
    await async2()
    console.log("async1 end")
}
function async2(){ // 去掉了 async 關鍵字
    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ù)的例子。一般來說,我們有一個業(yè)務需要分不完成,每個步驟都是異步的,并且嚴重依賴于上一步的執(zhí)行結果,稍有不慎就會進入回調(diào)地獄(callback hell)了,這種情況下,我們可以用 async / await 來完成

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

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

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

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

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

舉一個例子:

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

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

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

async created() {
    const userInfo = this.getUserInfo(); // 它們都會返回 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、小結

1、異步的終極解決方案

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

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

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

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

7、寫在最后

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

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

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99662.html

相關文章

  • 真的會用 Babel ?

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

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

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

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

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

    IntMain 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<