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

資訊專欄INFORMATION COLUMN

async函數(shù)學(xué)習(xí)筆記。

sewerganger / 1956人閱讀

摘要:基本用法函數(shù)返回一個(gè)對(duì)象,可以使用方法添加回調(diào)函數(shù)。拋出的錯(cuò)誤對(duì)象會(huì)被方法回調(diào)函數(shù)接收到。也就是說,只有函數(shù)內(nèi)部的異步操作執(zhí)行完,才會(huì)執(zhí)行方法指定的回調(diào)函數(shù)。命令后面的對(duì)象如果變?yōu)闋顟B(tài),則的參數(shù)會(huì)被方法的回調(diào)函數(shù)接收到。

含義

async函數(shù)是什么?一句話,它就是Generator函數(shù)的語法糖。

const fs = require("fs")
const readFile = function(fileName){
    return new Promise(function(resolve,reject){
        fs.readFile(fileName,function(error,data){
            if(error) return reject(error);
            resolve(data);
        })
    })
}
const gen = function*(){
    const f1 = yield readFile("/etc/fstab");
    const f2 = yield readFile("/etc/shells");
    console.log(f1.toString());
    console.log(f2.toString());
}
//上面代碼的函數(shù)gen可以寫成async函數(shù),就是下面這樣。
const asyncReadFile = async function(){
    const f1 = await readFile("/etc/fstab");
    cosnt f2 = await readFile("/etc/shells");
    console.log(f1.toString());
    console.log(f2.toString());
}

一比較就會(huì)發(fā)現(xiàn),async函數(shù)就是將Generator函數(shù)的星號(hào)替換成async,將yield替換成await,僅此而已。
async函數(shù)對(duì)Generator函數(shù)的改進(jìn),體現(xiàn)在以下四點(diǎn)。
(1)內(nèi)置執(zhí)行器
Generator函數(shù)的執(zhí)行必須靠執(zhí)行器,所以才有了co模塊,而async函數(shù)自帶執(zhí)行器。也就是說,async函數(shù)的執(zhí)行,與普通函數(shù)一模一樣,只要一行。

asyncReadFile()

上面的代碼調(diào)用了asyncReadFile函數(shù),然后它就會(huì)自動(dòng)執(zhí)行,輸出最后結(jié)果。這完全不像Generator函數(shù),需要調(diào)用next方法,或則用co模塊,才能真正執(zhí)行,得到最后結(jié)果。
(2)更好的語義
async和await,比起星號(hào)和yield,語義更清楚了。async表示函數(shù)里有異步操作,await表示緊跟在后面的表達(dá)式需要等待結(jié)果。
(3)更廣的適用性
co模塊約定,yield命令后面只能是Thunk函數(shù)或Promise對(duì)象,而async函數(shù)的await命令后面,可以是Promise對(duì)象和原始類型的值(數(shù)值、字符串和布爾值,但這時(shí)等同于同步操作)。
(4)返回值是Promise
async函數(shù)的返回值是Promise對(duì)象,這比Generator函數(shù)的返回值Iterator對(duì)象方便多了。你可以用then方法指定下一步的操作。
進(jìn)一步說,async函數(shù)完全可以看作多個(gè)異步操作,包裝成的一個(gè)Promise對(duì)象,而await命令就是內(nèi)部then命令的語法糖。

基本用法

async函數(shù)返回一個(gè)Promise對(duì)象,可以使用then方法添加回調(diào)函數(shù)。當(dāng)函數(shù)執(zhí)行的時(shí)候,一旦遇到await就會(huì)先返回,等到異步操作完成,再接著執(zhí)行函數(shù)體內(nèi)后面的語句。
下面是一個(gè)例子。

async function getStockPriceByName(name){
    const symbol = await getStockSymbol(name);
    const stockPrice = await getStockPrice(symbol);
    return stockPrice;
}
getStockPriceByName("goog").then(function(result){
    console.log(result);
})

上面代碼是一個(gè)獲取股票報(bào)價(jià)的函數(shù),函數(shù)前面的async關(guān)鍵字,表明該函數(shù)內(nèi)部有異步操作。調(diào)用該函數(shù)時(shí),會(huì)立即返回一個(gè)Promise對(duì)象。
下面是另一個(gè)例子,指定多少毫秒后輸出一個(gè)值。

function timeout(ms){
    return new Promise((resolve)=>{
        setTimeout(resolve,ms);
    })
}
async function asyncPrint(value,ms){
    await timeout(ms);
    console.log(value)
}
asyncPrint("hello world",50);

由于async函數(shù)返回的是Promise對(duì)象,可以作為await命令的參數(shù)。所以,上面的例子也可以寫成下面的形式。

async function timeout(ms){
    await new Promise((resolve)=>{
        setTimeout(resolve,ms);
    })
}

async function asyncPrint(value, ms) {
    await timeout(ms);
    console.log(value);
}

asyncPrint("hello world", 5000);

async函數(shù)有多種使用形式。

//函數(shù)聲明
async function foo(){}
//函數(shù)表達(dá)式
const foo = async function(){};
//對(duì)象的方法
let obj = {async foo(){}};
obj.foo().then(...)
//Class的方法
class Storage{
    constructor(){
        this.cachePromise = caches.open("avatars");
    }
    async getAvatar(name){
        const cache = await this.cachePromise;
        return cache.match(`/avatars/${name}.jpg`);
    }
}
const storage = new Storage();
storage.getAvatar("jake").then(...);
//箭頭函數(shù)
const foo = async()=>{};
返回Promise對(duì)象

async函數(shù)返回一個(gè)Promise對(duì)象。
async函數(shù)內(nèi)部return語句返回的值,會(huì)成為then方法回調(diào)函數(shù)的參數(shù)。

async function f(){
    return "hello world";
}
f().then(v=>console.log(v))//"hello world"

上面代碼中,函數(shù)f內(nèi)部return命令返回的值,會(huì)被then方法回調(diào)函數(shù)接收到。
async函數(shù)內(nèi)部拋出錯(cuò)誤,會(huì)導(dǎo)致返回Promise對(duì)象變?yōu)閞eject狀態(tài)。拋出的錯(cuò)誤對(duì)象會(huì)被catch方法回調(diào)函數(shù)接收到。

async function f(){
    throw new Error("出錯(cuò)了");
}
f().then(
    v=>console.log(v),
    e=>console.log(e)
)
//Error;出錯(cuò)了
Promise對(duì)象的狀態(tài)變化

async函數(shù)返回的Promise對(duì)象,必須等到內(nèi)部所有await命令后面的Promise對(duì)象執(zhí)行完,才會(huì)發(fā)生狀態(tài)改變,除非遇到return語句或則拋出錯(cuò)誤。也就是說,只有async函數(shù)內(nèi)部的異步操作執(zhí)行完,才會(huì)執(zhí)行then方法指定的回調(diào)函數(shù)。

async function getTitle(url) {
  let response = await fetch(url);
  let html = await response.text();
  return html.match(/([sS]+)/i)[1];
}
getTitle("https://tc39.github.io/ecma262/").then(console.log)

上面代碼中,函數(shù)getTitle內(nèi)部有三個(gè)操作:抓取網(wǎng)頁、取出文本、匹配頁面標(biāo)題。只有這三個(gè)操作全部完成,才會(huì)執(zhí)行then方法里面的console.log()
await命令
正常情況下,await命令后面是一個(gè)Promise對(duì)象,返回該對(duì)象的結(jié)果。如果不是Promsie對(duì)象,就直接返回對(duì)應(yīng)的值。

async function f(){
    //等同于123;
    return await 123;
}
f().then(v=>console.log(v))

上面代碼中,await命令的參數(shù)是數(shù)值123,這時(shí)等同于return 123.
另一種情況是,await命令后面是一個(gè)thenable對(duì)象(即定義then方法的對(duì)象),那么await會(huì)將其等同于Promise對(duì)象。

class Sleep{
    constructor(timeout){
        this.timeout = timeout;
    }
    then(resolve,reject){
        const startTime = Date.now();
        setTimeout(
            ()=>resolve(Date.now()-startTime)
            this.timeout
        )
    }
}
(async()=>{
    const actualTime = await new Sleep(1000);
    console.log(actualTime);
})();

上面代碼中,await命令后面是一個(gè)Sleep對(duì)象的實(shí)例。這個(gè)實(shí)例不是Promise對(duì)象,但是因?yàn)槎x了then方法,await會(huì)將其視為Promise處理。
await命令后面的Promise對(duì)象如果變?yōu)閞eject狀態(tài),則reject的參數(shù)會(huì)被catch方法的回調(diào)函數(shù)接收到。

async function f(){
    await Promise.reject("出錯(cuò)了");
}
f().then(v=>console.log(v)).catch(e=>console.log(e));

注意,上面代碼中,await語句前面沒有return,但是reject方法的參數(shù)依然傳入到catch方法的回調(diào)函數(shù)。這里如果是await前面加上return,效果是一樣的。
任何一個(gè)await語句后面的Promise對(duì)象變?yōu)閞eject狀態(tài),那么整個(gè)async函數(shù)都會(huì)中斷執(zhí)行。
有時(shí),我們希望即使前一個(gè)異步操作失敗,也不要中斷后面的異步操作。這時(shí)可以將第一個(gè)await放在try...catch結(jié)構(gòu)里面,這樣不管這個(gè)異步操作是否成功,第二個(gè)await都會(huì)執(zhí)行。

async function f(){
    try{
        await Promise.reject("出錯(cuò)了");
    }catch(e){
    }
    return await Promise.resolve("hello world");
}
f().then(v=>console.log(v))//hello world

另一種方法是await后面的Promise對(duì)象再跟一個(gè)catch方法,處理前面可能出現(xiàn)的錯(cuò)誤。

async function f(){
    await Promise.reject("出錯(cuò)了")
        .catch(e=>console.log(e));
    return await Promise.resolve("hello world");
}
f().then(v=>console.log(v))
//出錯(cuò)了
//hello world

錯(cuò)誤處理
如果await后面的異步操作出錯(cuò),那么等同于async函數(shù)返回的Promise對(duì)象被reject。防止出錯(cuò)的方法,也是將其放在try...catch代碼塊之中。

async function f(){
    try{
        await new Promise(function(resolve,reject){
            throw new Error("出錯(cuò)了")
        });
    }catch(e){}
    return await("hello world");
}

如果有多個(gè)await命令,可以統(tǒng)一放在try...catch結(jié)構(gòu)中。

async function main(){
    try{
        const val1 = await firstStep();
        const val2 = await secondStep(val1);
        const val3 = await thirdStep(val1,val2);
        console.log("Final",val3);
    }
    catch(err){
        console.error(err);
    }
}

下面的例子使用try...catch結(jié)構(gòu),實(shí)現(xiàn)多次重復(fù)嘗試。

const superagent = require("superagent");
const NUM_RETRIES = 3;
async function test(){
    let i;
    for(i=0;i

上面代碼中,如果await操作成功,就會(huì)使用break語句退出循環(huán);如果失敗,會(huì)被catch語句捕捉,然后進(jìn)入下一輪循環(huán)。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/100281.html

相關(guān)文章

  • 重學(xué)前端學(xué)習(xí)筆記(十七)--Promise里的代碼為什么比setTimeout先執(zhí)行?

    摘要:版本以及之前,本身還沒有異步執(zhí)行代碼的能力,宿主環(huán)境傳遞給引擎,然后按順序執(zhí)行,由宿主發(fā)起任務(wù)。采納引擎術(shù)語,把宿主發(fā)起的任務(wù)稱為宏觀任務(wù),把引擎發(fā)起的任務(wù)稱為微觀任務(wù)?;居梅ㄊ纠幕卣{(diào)是一個(gè)異步的執(zhí)行過程。 筆記說明 重學(xué)前端是程劭非(winter)【前手機(jī)淘寶前端負(fù)責(zé)人】在極客時(shí)間開的一個(gè)專欄,每天10分鐘,重構(gòu)你的前端知識(shí)體系,筆者主要整理學(xué)習(xí)過程的一些要點(diǎn)筆記以及感悟,完整的...

    pinecone 評(píng)論0 收藏0
  • 重學(xué)前端學(xué)習(xí)筆記(十七)--Promise里的代碼為什么比setTimeout先執(zhí)行?

    摘要:版本以及之前,本身還沒有異步執(zhí)行代碼的能力,宿主環(huán)境傳遞給引擎,然后按順序執(zhí)行,由宿主發(fā)起任務(wù)。采納引擎術(shù)語,把宿主發(fā)起的任務(wù)稱為宏觀任務(wù),把引擎發(fā)起的任務(wù)稱為微觀任務(wù)。基本用法示例的回調(diào)是一個(gè)異步的執(zhí)行過程。 筆記說明 重學(xué)前端是程劭非(winter)【前手機(jī)淘寶前端負(fù)責(zé)人】在極客時(shí)間開的一個(gè)專欄,每天10分鐘,重構(gòu)你的前端知識(shí)體系,筆者主要整理學(xué)習(xí)過程的一些要點(diǎn)筆記以及感悟,完整的...

    zorpan 評(píng)論0 收藏0
  • 重學(xué)前端學(xué)習(xí)筆記(十七)--Promise里的代碼為什么比setTimeout先執(zhí)行?

    摘要:版本以及之前,本身還沒有異步執(zhí)行代碼的能力,宿主環(huán)境傳遞給引擎,然后按順序執(zhí)行,由宿主發(fā)起任務(wù)。采納引擎術(shù)語,把宿主發(fā)起的任務(wù)稱為宏觀任務(wù),把引擎發(fā)起的任務(wù)稱為微觀任務(wù)?;居梅ㄊ纠幕卣{(diào)是一個(gè)異步的執(zhí)行過程。 筆記說明 重學(xué)前端是程劭非(winter)【前手機(jī)淘寶前端負(fù)責(zé)人】在極客時(shí)間開的一個(gè)專欄,每天10分鐘,重構(gòu)你的前端知識(shí)體系,筆者主要整理學(xué)習(xí)過程的一些要點(diǎn)筆記以及感悟,完整的...

    xiongzenghui 評(píng)論0 收藏0
  • 重學(xué)前端學(xué)習(xí)筆記(十九)--JavaScript中的函數(shù)

    摘要:方法在中定義的函數(shù)。這種聲明方式會(huì)定義一個(gè)生成器函數(shù),它返回一個(gè)對(duì)象。類用定義的類,實(shí)際上也是函數(shù)。調(diào)用函數(shù)時(shí)使用的引用,決定了函數(shù)執(zhí)行時(shí)刻的值。表示當(dāng)為時(shí),取全局對(duì)象,對(duì)應(yīng)了普通函數(shù)。四操作的內(nèi)置函數(shù)和可以指定函數(shù)調(diào)用時(shí)傳入的值。 筆記說明 重學(xué)前端是程劭非(winter)【前手機(jī)淘寶前端負(fù)責(zé)人】在極客時(shí)間開的一個(gè)專欄,每天10分鐘,重構(gòu)你的前端知識(shí)體系,筆者主要整理學(xué)習(xí)過程的一些要...

    genefy 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

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