成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

ES6&ES7中的異步之a(chǎn)sync函數(shù)

dongxiawu / 1162人閱讀

摘要:更好的語(yǔ)義和分別表示異步和等待,比起和更容易理解。前邊聲明關(guān)鍵字,表示內(nèi)部有內(nèi)部操作,調(diào)用函數(shù)會(huì)返回一個(gè)對(duì)象。等價(jià)于其中函數(shù)就是自動(dòng)執(zhí)行器。

async函數(shù) 定義

async函數(shù)其實(shí)就是之前說(shuō)過(guò)的Generator的語(yǔ)法糖,用于實(shí)現(xiàn)異步操作。它是ES2017的新標(biāo)準(zhǔn)。

讀取兩個(gè)文件:

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 gen1 = yield readFile("../1.txt")
    const gen2 = yield readFile("../2.txt")
    console.log(gen1.toString())
    console.log(gen2.toString())
}

如果使用async函數(shù)的話,會(huì)是這么寫(xiě)

const _readFile = async function(){
    const r1 = await readFile("../3.txt")
    const r2 = await readFile("../4.txt")
    console.log(r1.toString())
    console.log(r2.toString())
}

一般情況下,只是把Generator的*換成async,把yield換成await。
async函數(shù)是Generator函數(shù)的改進(jìn),具體體現(xiàn)在四點(diǎn)

1.內(nèi)置執(zhí)行器:

相對(duì)于Generator函數(shù)需要co模塊或者next()方法來(lái)作為執(zhí)行器執(zhí)行,async函數(shù)自帶執(zhí)行器,所以上邊的代碼只需要一句

_readFile()   

可以執(zhí)行。

2.更好的語(yǔ)義:

async和await分別表示異步和等待,比起*和yield更容易理解。

3.更廣泛的適用性:
yield后邊只能跟Thunk函數(shù)或者Promise對(duì)象,但是在async函數(shù)中,可以跟Promise對(duì)象和基本數(shù)據(jù)類(lèi)型。

4.返回值是Promise

相比于Generator函數(shù)返回一個(gè)Iterator還需要遍歷,async直接返回一個(gè)Promise可以直接調(diào)用then方法和catch方法。

基本用法

async函數(shù)返回一個(gè)Promise對(duì)象,可以使用then方法添加回調(diào),然后使用await關(guān)鍵字后,會(huì)等到異步操作執(zhí)行完在執(zhí)行后邊的語(yǔ)句。

async function getPriceByName(name){
    const symbol = await getSymbod(name)
    const price = await getPrice(symbol)
    return price
}

getPriceByName("WUBA").then(function(result){
    console.log(result)
})

上邊的例子,是一個(gè)通過(guò)股票的名稱,獲得股票的代碼,再獲得價(jià)錢(qián)。前邊聲明async關(guān)鍵字,表示內(nèi)部有內(nèi)部操作,調(diào)用函數(shù)會(huì)返回一個(gè)Promise對(duì)象。

再看下一個(gè)例子,是一個(gè)指定多少毫秒后返回一個(gè)值。

function TimeOut(time){
    return new Promise(function(resolve)){
        setTimeout(resolve,time)
    }
}

async asyncTimeOut = function(value,time){
    const t1 = await TimeOut(time)
    console.log(t1)
}

asyncTimeOut("hello",1000)
asyncTimeOut("world",2000)

async函數(shù)的多種形式

函數(shù)表達(dá)式
const fun1 = async function(){
    ....
}

函數(shù)聲明
async function fun2(){
    ....
}

箭頭函數(shù)
const fun3 = async () => {
    ....
}

對(duì)象中的變量
let obj = {
    async fun4(){
        ....
    }
}
obj.fun4()

類(lèi)的寫(xiě)法
class Async {
    constructor(){}
    
    async fun5(){
        ....
    }
}
const a1 = new Async()
a1.fun5().then()
語(yǔ)法 返回一個(gè)Promise對(duì)象

說(shuō)過(guò)很多次了,async函數(shù)返回一個(gè)Promise對(duì)象。
函數(shù)return的值將會(huì)作為then方法的參數(shù)

async function show(){
    return "123"
}

show().then((v) => console.log(v))

show方法返回的值會(huì)被作為then方法的參數(shù)而調(diào)用。

如果在async函數(shù)內(nèi)部拋出錯(cuò)誤,會(huì)被catch捕獲,這個(gè)時(shí)候Promise對(duì)象變成reject狀態(tài)。

async function show2(){
    throw new Error("出錯(cuò)了")
}

show2().then(
    v => console.log(v),
    e => console.log(e)
)
Promise的狀態(tài)改變

async函數(shù)返回的Promise對(duì)象,必須等到函數(shù)內(nèi)部所有的await執(zhí)行完才會(huì)發(fā)生狀態(tài)的變化,也就是說(shuō),得等到所有await執(zhí)行完,才會(huì)執(zhí)行后續(xù)的then方法。

async function getText(url){
    const response = await fetch(url)
    const text = await response.text()
    return text.match("../aa/[a-z]}")[1]   //反正就是一個(gè)正則匹配
}

const url = "...."
getText(url).then(v => console.log(v))

這個(gè)例子說(shuō)明,得等到兩個(gè)awiat都執(zhí)行完才會(huì)console返回的數(shù)據(jù)。

await命令

前邊說(shuō)過(guò),await命令后邊跟隨一個(gè)Promise對(duì)象。如果不是,會(huì)被轉(zhuǎn)成Promise對(duì)象。

async function show(){
    return await "123"
}

show().then((v) => console.log(v))

如果await后邊的Promise對(duì)象變成了reject狀態(tài),會(huì)被后邊的catch()捕獲。

async function fun1() {
    return await Promise.reject("出錯(cuò)了")
}

fun1().catch(e => console.log(e))

如果async函數(shù)內(nèi)部有多個(gè)await,但是只要一個(gè)await返回的Promise對(duì)象變成了reject狀態(tài),則整個(gè)函數(shù)立刻捕獲異常。

如果想要前邊的正常拋出異常而不影響后邊的await語(yǔ)句執(zhí)行,可以把前邊的寫(xiě)進(jìn)一個(gè)try/catch中去。

async function fun2(){
    try{
        await Promise.reject("出錯(cuò)了")
    }catch(e){
    }
    
    await Promise.resolev("hello")
}

fun2().then(v => console.log(v))
使用的注意點(diǎn)

由于await后面跟隨的是Promise對(duì)象,所以對(duì)象可能會(huì)有兩個(gè)狀態(tài),一個(gè)resolve一個(gè)reject。所以,最好把a(bǔ)wait代碼放到try/catch語(yǔ)句中比較好。

async function fun3(){
    try{
        await asyncFun1()
        await asyncFun2()
    } catch(e){
        console.log(e)
    }
}

// 還有另外一種寫(xiě)法
async function fun4(){
    await asyncFun1().catch(e => console.log(e))
    await asyncFun2().catch(e => console.log(e))
}

還是第一種方法更好一點(diǎn)。直接寫(xiě)進(jìn)try/catch語(yǔ)句中。

最好讓多個(gè)await后邊的異步操作同時(shí)發(fā)生,如果不是不存在先后順序的話。

let a1 = await get1()
let a2 = await get2()

上邊的寫(xiě)法,get1執(zhí)行完之后才會(huì)執(zhí)行g(shù)et2,如果get1和get2沒(méi)有直接的關(guān)聯(lián),那樣會(huì)很浪費(fèi)時(shí)間。

//同時(shí)觸發(fā)
let [a1,a2] = await Promise.all([get1(),get2()])

如果await放到async函數(shù)之外,就會(huì)報(bào)錯(cuò),只能放到async函數(shù)內(nèi)部。

async的原理

原理也很簡(jiǎn)單,就是把Generator函數(shù)和自動(dòng)執(zhí)行器包裝在一個(gè)函數(shù)中。

async function fn(){
    .....
}

// 等價(jià)于
function fn(){
    return spawn(function *(){
        .....
    })
}

其中spawn函數(shù)就是自動(dòng)執(zhí)行器。

function spawn(genF) {
  return new Promise(function(resolve, reject) {
    const gen = genF();
    function step(nextF) {
      let next; 
      try {
        next = nextF();
      } catch(e) {
        return reject(e);
      }
      if(next.done) {
        return resolve(next.value);
      }
      Promise.resolve(next.value).then(function(v) {
        step(function() { return gen.next(v); });
      }, function(e) {
        step(function() { return gen.throw(e); });
      });
    }
    step(function() { return gen.next(undefined); });
  });
}
實(shí)例:按照順序完成異步操作

實(shí)際開(kāi)發(fā)中經(jīng)常會(huì)遇到各種異步操作,這里有一個(gè)例子。一次讀取一組url,然后按照讀取的順序返回結(jié)果。

function readUrls(urls) {
    const textPromise = urls.map(url => {
        fetch(url).then(response => response.text())
    })
    
    // 按照順序讀出
    textPromise.reduce((chain,textPromise) => {
        return chain.then(() => textPromise)
        .then(text => console.log(text));
    },Promise.resolve())
} 

分析一下,上邊的代碼,用fetch同時(shí)讀取一種url,每個(gè)fetch操作都返回一個(gè)Promise對(duì)象,放入textPromise數(shù)組,然后reduce方法一次處理每個(gè)Promise對(duì)象,然后用then連接起來(lái),一次輸出結(jié)果。

缺點(diǎn):這種方法看起來(lái)不太好理解,不太直觀,用async函數(shù)會(huì)更好一點(diǎn)。

async function readUrls(urls){
    for(const url of urls){
        const response = await fetch(url)
        console.log(response.text())
    }
}

可以看到,代碼是大大簡(jiǎn)化了,但是會(huì)有一個(gè)新的問(wèn)題,就是必須等到前邊一個(gè)讀完了,才會(huì)讀取下一個(gè)數(shù)據(jù)。

function readUrls(urls){
    const textPromise = urls.map(async url => {
        const response = await fetch(url)
        return response.text()
    })
}

//按照順序輸出
for(const text of textPromise){
    console.log(await text)
}

上邊的函數(shù),雖然map方法的參數(shù)是async函數(shù),但卻是并發(fā)執(zhí)行的,因?yàn)閮?nèi)部是繼發(fā)執(zhí)行,不影響外部。在后邊的循環(huán)中使用了await,這樣,還是會(huì)依次輸出。

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

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

相關(guān)文章

  • ES6&ES7中的異步Generator函數(shù)異步編程

    摘要:傳統(tǒng)的異步方法回調(diào)函數(shù)事件監(jiān)聽(tīng)發(fā)布訂閱之前寫(xiě)過(guò)一篇關(guān)于的文章,里邊寫(xiě)過(guò)關(guān)于異步的一些概念。內(nèi)部函數(shù)就是的回調(diào)函數(shù),函數(shù)首先把函數(shù)的指針指向函數(shù)的下一步方法,如果沒(méi)有,就把函數(shù)傳給函數(shù)屬性,否則直接退出。 Generator函數(shù)與異步編程 因?yàn)閖s是單線程語(yǔ)言,所以需要異步編程的存在,要不效率太低會(huì)卡死。 傳統(tǒng)的異步方法 回調(diào)函數(shù) 事件監(jiān)聽(tīng) 發(fā)布/訂閱 Promise 之前寫(xiě)過(guò)一篇關(guān)...

    venmos 評(píng)論0 收藏0
  • ES6-7

    摘要:的翻譯文檔由的維護(hù)很多人說(shuō),阮老師已經(jīng)有一本關(guān)于的書(shū)了入門(mén),覺(jué)得看看這本書(shū)就足夠了。前端的異步解決方案之和異步編程模式在前端開(kāi)發(fā)過(guò)程中,顯得越來(lái)越重要。為了讓編程更美好,我們就需要引入來(lái)降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(shū)(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會(huì)promise...... 本書(shū)的目的是以目前還在制定中的ECMASc...

    mudiyouyou 評(píng)論0 收藏0
  • Promise & Generator——幸福地用同步方法寫(xiě)異步JavaScript

    摘要:在這里看尤雨溪大神的這篇小短文,非常精簡(jiǎn)扼要地介紹了當(dāng)前常用的。根據(jù)尤雨溪大神的說(shuō)法,的也只是的語(yǔ)法糖而已。對(duì)象有三種狀態(tài),,。對(duì)象通過(guò)和方法來(lái)規(guī)定異步結(jié)束之后的操作正確處理函數(shù)錯(cuò)誤處理函數(shù)。方便進(jìn)行后續(xù)的成功處理或者錯(cuò)誤處理。 最近在寫(xiě)一個(gè)自己的網(wǎng)站的時(shí)候(可以觀摩一下~Colors),在無(wú)意識(shí)中用callback寫(xiě)了一段嵌套了5重回調(diào)函數(shù)的可怕的代碼。回過(guò)神來(lái)的時(shí)候被自己嚇了一跳,...

    Harpsichord1207 評(píng)論0 收藏0
  • 翻譯:Taming the asynchronous beast with ES7

    摘要:讓我們使用它從數(shù)組中返回一個(gè)值數(shù)組在中,我們可以這樣做,這是一種更簡(jiǎn)單的方法最重要的部分是創(chuàng)建數(shù)組,該數(shù)組立即調(diào)用所有的我們?cè)谥骱瘮?shù)中等待這些。所以在我們真正等待完成之前,主函數(shù)就退出了。 原文:https://pouchdb.com/2015/03/0... PouchDB最棘手的方面之一是它的API是異步的。在Stack Overflow、Github和IRC上,我看到了不少困惑的...

    Eastboat 評(píng)論0 收藏0
  • ES6&ES7中的異步Generator的語(yǔ)法

    摘要:第二次同理,遇到了第二個(gè)函數(shù)會(huì)停下來(lái),輸出的遍歷器對(duì)象值為,的值依然是。比如返回的遍歷器對(duì)象,都會(huì)有一個(gè)方法,這個(gè)方法掛在原型上。這三個(gè)函數(shù)共同的作用是讓函數(shù)恢復(fù)執(zhí)行。 Generator的語(yǔ)法 generator的英文意思是生成器 簡(jiǎn)介 關(guān)于Generator函數(shù),我們可以理解成是一個(gè)狀態(tài)機(jī),里面封裝了多種不同的狀態(tài)。 function* gener(){ yield hel...

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

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

0條評(píng)論

閱讀需要支付1元查看
<