亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

js異步從入門到放棄(四)- Generator 封裝異步任務(wù)

jimhs / 2491人閱讀

摘要:總結(jié)本文簡(jiǎn)要介紹了函數(shù)的一些特性,重點(diǎn)在于說明如何使用函數(shù)對(duì)異步任務(wù)進(jìn)行封裝,從而能夠讓異步代碼編寫的更加清晰。

在之前的文章介紹了傳統(tǒng)異步的實(shí)現(xiàn)方案,本文將介紹ES6中的一種全新的異步方案--Generator函數(shù)。

generator簡(jiǎn)介

簡(jiǎn)單介紹一下generator的原理和語法,(更詳細(xì)內(nèi)容請(qǐng)看ECMAScript 6 入門,本文只介紹和異步相關(guān)的核心內(nèi)容)

基本語法

通過一個(gè)簡(jiǎn)單的例子來了解generator函數(shù)

function* MyGenerator() {
    yield "yield的含義是:執(zhí)行此處時(shí),暫停執(zhí)行當(dāng)前函數(shù)"
    yield "暫停之后的函數(shù)可以用next方法繼續(xù)執(zhí)行"
    return "遇到return之后會(huì)真正結(jié)束,done會(huì)變成true"
}

const gen = MyGenerator() //執(zhí)行后返回的是一個(gè)指針,可以利用該指針執(zhí)行next方法
console.log(gen.next()) // {value: "yield的含義是:執(zhí)行此處時(shí),暫停執(zhí)行當(dāng)前函數(shù)“, done: false}
console.log(gen.next())// {value: "暫停之后的函數(shù)可以用next方法繼續(xù)執(zhí)行", done: false}
console.log(gen.next())// {value: "遇到return之后會(huì)真正結(jié)束,done會(huì)變成true", done: true}
數(shù)據(jù)交互

數(shù)據(jù)交互指的是可以通過yield把當(dāng)前執(zhí)行的結(jié)果傳出,也可以使用next把外部參數(shù)傳入

    function* MyGenerator(){
        const result = yield "傳出的數(shù)據(jù)"
        return result
    }
    const gen = MyGenerator()
    console.log(gen.next())// generatorAndAsync2.html:19 {value: "傳出的數(shù)據(jù)", done: false}
    console.log(gen.next("傳入的數(shù)據(jù)"))// {value: "傳入的數(shù)據(jù)", done: true}

交互的參數(shù)類型當(dāng)然也可以是函數(shù)

    function sayHi(){
        console.log("hi");
    }
    
    function* MyGenerator(){
        const result = yield sayHi()
        return 
    }
    
    const gen = MyGenerator()
    const result = gen.next()// {value: sayHi, done: false}
    result.value() // 正常輸出"hi"

具備以上最核心的兩個(gè)特性之后,generator就可以進(jìn)行異步操作封裝。

異步任務(wù)封裝

首先,結(jié)合異步任務(wù)的特點(diǎn)以及前文提到的genrator函數(shù)的特性,提煉出使用generator封裝異步操作的核心思路:

在異步任務(wù)執(zhí)行時(shí),使用yield交出執(zhí)行權(quán)

在異步任務(wù)結(jié)束后,使用next交還執(zhí)行權(quán)

起步

從一個(gè)最簡(jiǎn)單的例子開始:

// 1. 首先寫一個(gè)異步任務(wù),在一秒后返回特定字符串
function asyncTask(callback){
    setTimeout(()=>{
        callback("Hello Leo")
    }, 1000)
}

// 2. 接下來寫出期望執(zhí)行的順序
function* runTask() {
    let text = yield asyncTask
    console.log(text) // 我們期望這里正常輸出Hello Leo
}
// 3. 按照期望值執(zhí)行函數(shù)
const gen = runTask()// 此時(shí)執(zhí)行權(quán)已經(jīng)交出
gen.next().value(function (text) {// 執(zhí)行asyncTask并傳入callback ,關(guān)鍵點(diǎn)在于在callback里調(diào)用next交還執(zhí)行權(quán)
    gen.next(text)
}) 

首先,這段代碼雖然很粗糙,但是已經(jīng)反映了使用generator封裝異步任務(wù)的核心思想。最直觀的受益就是:runTask的內(nèi)容看起來很像同步代碼,條理清晰,很適合閱讀。

但是上面第3部分關(guān)于執(zhí)行的代碼很不靈活,我們不能每次都這么寫一段,因此接下來的目標(biāo)就是實(shí)現(xiàn)一個(gè)任務(wù)執(zhí)行器。

自動(dòng)任務(wù)執(zhí)行器

同樣的,先思考核心的思路:要想讓某個(gè)generator函數(shù)自動(dòng)執(zhí)行,無非就是一個(gè)while循環(huán):

1. 如果當(dāng)前yield返回值的done屬性為true,說明任務(wù)已經(jīng)執(zhí)行完成;
2. 如果當(dāng)前yield返回值的done屬性為false,說明任務(wù)還未執(zhí)行完成,則繼續(xù)執(zhí)行next,同時(shí)要注意參數(shù)傳遞

根據(jù)分析實(shí)現(xiàn)以下的執(zhí)行器:

function autoExecute(task) {
    const gen = task()
    let result = gen.next()
    while(true){
        if(result.done){
            break // 執(zhí)行結(jié)束
            return 
        }
        console.log(result.value)//為了便于觀察 我們加上console.log
        result = gen.next(result.value) // 每次都應(yīng)該重寫result 獲取最新結(jié)果
    }
}

function* simpleTask(){
    yield 1
    yield 2
    yield 3
    return 
}

autoExecute(simpleTask)// 測(cè)試我們寫的自動(dòng)執(zhí)行器 能夠正確輸出123

上面的執(zhí)行器已經(jīng)有了雛形,但是對(duì)于前面例子中,result.value為函數(shù)的情況還沒有處理,因此還需要稍微補(bǔ)充:

function isFunction(source){
     return Object.prototype.toString.call(source) === "[object Function]"
}

function autoExecute(task) {
    const gen = task()
    let result = gen.next()
    let isRuningAsync = false // 由于加入了異步處理,所以要增加一個(gè)標(biāo)志位避免重復(fù)進(jìn)入循環(huán)體
    while (!isRuningAsync) {
        if (result.done) {
            return
        }
        console.log(result.value)

        /* start 補(bǔ)充的處理函數(shù) */
        if (isFunction(result.value)) {
            isRuningAsync = true
            const callback = (arg) => {
                result = gen.next(arg) // 核心代碼
                isRuningAsync = false
            }
            result.value(callback)
            /* end 補(bǔ)充的處理函數(shù) */
        } else {
            result = gen.next(result.value)
        }
    }
}
autoExecute(runTask) // 試著用這個(gè)自動(dòng)執(zhí)行器執(zhí)行之前的異步任務(wù)

上面這個(gè)自動(dòng)執(zhí)行器,就完成了generator對(duì)異步任務(wù)的封裝。

總結(jié)

本文簡(jiǎn)要介紹了generator函數(shù)的一些特性,重點(diǎn)在于說明如何使用generator函數(shù)對(duì)異步任務(wù)進(jìn)行封裝,從而能夠讓異步代碼編寫的更加清晰。

再次強(qiáng)調(diào):用generator函數(shù)對(duì)異步任務(wù)封裝的思想是很明確的--控制 Generator 函數(shù)的流程,在適當(dāng)?shù)臅r(shí)機(jī)接收和交還程序的執(zhí)行權(quán),但是具體的實(shí)現(xiàn)方式并不唯一,例如本文用的是最簡(jiǎn)單直接的回調(diào)函數(shù)方式,在阮一峰老師的《es6入門》教程里,也有使用thunk思路來講解的部分,可以自行查閱。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/109850.html

相關(guān)文章

  • js異步入門放棄(實(shí)踐篇) — 常見寫法&面試題解析

    摘要:前文該系列下的前幾篇文章分別對(duì)不同的幾種異步方案原理進(jìn)行解析,本文將介紹一些實(shí)際場(chǎng)景和一些常見的面試題。流程調(diào)度里比較常見的一種錯(cuò)誤是看似串行的寫法,可以感受一下這個(gè)例子判斷以下幾種寫法的輸出結(jié)果辨別輸出順序這類題目一般出現(xiàn)在面試題里。 前文 該系列下的前幾篇文章分別對(duì)不同的幾種異步方案原理進(jìn)行解析,本文將介紹一些實(shí)際場(chǎng)景和一些常見的面試題。(積累不太夠,后面想到再補(bǔ)) 正文 流程調(diào)度...

    Awbeci 評(píng)論0 收藏0
  • JavaScript異步編程的終極演變

    摘要:在誕生以前,異步編程的方式大概有下面四種回調(diào)函數(shù)事件監(jiān)聽發(fā)布訂閱對(duì)象將異步編程帶入了一個(gè)全新的階段,中的函數(shù)更是給出了異步編程的終極解決方案。這意味著,出錯(cuò)的代碼與處理錯(cuò)誤的代碼,實(shí)現(xiàn)了時(shí)間和空間上的分離,這對(duì)于異步編程無疑是很重要的。 寫在前面 有一個(gè)有趣的問題: 為什么Node.js約定回調(diào)函數(shù)的第一個(gè)參數(shù)必須是錯(cuò)誤對(duì)象err(如果沒有錯(cuò)誤,該參數(shù)就是null)? 原因是執(zhí)行回調(diào)函...

    whjin 評(píng)論0 收藏0
  • 談?wù)凟S6前后的異步編程

    摘要:回調(diào)函數(shù)這是異步編程最基本的方法。對(duì)象對(duì)象是工作組提出的一種規(guī)范,目的是為異步編程提供統(tǒng)一接口。誕生后,出現(xiàn)了函數(shù),它將異步編程帶入了一個(gè)全新的階段。 更多詳情點(diǎn)擊http://blog.zhangbing.club/Ja... Javascript 語言的執(zhí)行環(huán)境是單線程的,如果沒有異步編程,根本沒法用,非卡死不可。 為了解決這個(gè)問題,Javascript語言將任務(wù)的執(zhí)行模式分成兩種...

    fizz 評(píng)論0 收藏0
  • 我了解的JavaScript異步編程

    摘要:接下來我們看下三類異步編程的實(shí)現(xiàn)。事件監(jiān)聽事件發(fā)布訂閱事件監(jiān)聽是一種非常常見的異步編程模式,它是一種典型的邏輯分離方式,對(duì)代碼解耦很有用處。 一、 一道面試題 前段時(shí)間面試,考察比較多的是js異步編程方面的相關(guān)知識(shí)點(diǎn),如今,正好輪到自己分享技術(shù),所以想把js異步編程學(xué)習(xí)下,做個(gè)總結(jié)。下面這個(gè)demo 概括了大多數(shù)面試過程中遇到的問題: for(var i = 0; i < 3; i++...

    RichardXG 評(píng)論0 收藏0
  • ES6(一) —— 異步編程解決辦法[回調(diào)函數(shù)promise,generator,async]

    摘要:回調(diào)函數(shù)這是最原始的一種異步解決方法。從的對(duì)象演化而來對(duì)象是提出的一種對(duì)異步編程的解決方案,但它不是新的語法,而是一種新的寫法,允許將回調(diào)函數(shù)的嵌套改成鏈?zhǔn)秸{(diào)用。 一、前言 異步編程對(duì)JavaScript來說非常重要,因?yàn)镴avaScript的語言環(huán)境是單線程的,如果沒有異步編程將變得非常可怕,估計(jì)根本無法使用。這篇文章就來總結(jié)一下從最原始的回調(diào)函數(shù)到現(xiàn)在的ES6、ES7的新方法。 文...

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

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

0條評(píng)論

jimhs

|高級(jí)講師

TA的文章

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