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

資訊專欄INFORMATION COLUMN

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

venmos / 2136人閱讀

摘要:傳統(tǒng)的異步方法回調(diào)函數(shù)事件監(jiān)聽發(fā)布訂閱之前寫過一篇關(guān)于的文章,里邊寫過關(guān)于異步的一些概念。內(nèi)部函數(shù)就是的回調(diào)函數(shù),函數(shù)首先把函數(shù)的指針指向函數(shù)的下一步方法,如果沒有,就把函數(shù)傳給函數(shù)屬性,否則直接退出。

Generator函數(shù)與異步編程

因為js是單線程語言,所以需要異步編程的存在,要不效率太低會卡死。

傳統(tǒng)的異步方法

回調(diào)函數(shù)

事件監(jiān)聽

發(fā)布/訂閱

Promise

之前寫過一篇關(guān)于Promise的文章,里邊寫過關(guān)于異步的一些概念。這篇文章將會說一下Generator函數(shù)的異步應(yīng)用。

Generator函數(shù) 協(xié)程

多個線程互相合作完成任務(wù),在傳統(tǒng)的編程語言中(比如java),當A線程在執(zhí)行,執(zhí)行一段時間之后暫停,由B線程繼續(xù)執(zhí)行,B線程執(zhí)行結(jié)束之后A線程再執(zhí)行,這個時候,A線程就被稱為協(xié)程,而這個協(xié)程A就是異步任務(wù)。

function* foo(){
    ... //其他代碼
    var f = readFile();
    ... //其他代碼
}

上邊這個函數(shù),foo函數(shù)就是一個協(xié)程,通過yield命令實現(xiàn)協(xié)程的暫停,等到讀取文件的函數(shù)執(zhí)行完畢之后,再繼續(xù)執(zhí)行foo其他的操作。

協(xié)程的Generator函數(shù)實現(xiàn)

Generator函數(shù)是協(xié)程在ES6的實現(xiàn),最大的特點是交出函數(shù)的執(zhí)行權(quán)(暫停函數(shù)執(zhí)行)

整個Generator函數(shù)就是一個封裝好了的異步任務(wù),而yield是函數(shù)暫停執(zhí)行的標志。

function* foo(){
    let x = 1;
    let y = yield x + 2;
    return y
}

var f = foo()
f.next();   // {value:3,done:false}
f.next();   // {value:undefined,done:true}

next方法的作用是分批端執(zhí)行Generator函數(shù)。
異步函數(shù)的封裝
let fetch = require("node-fetch")

function* asynsFun(){
    let url = "....";
    var f = yield fetch(url);
    console.log(f)
}

當執(zhí)行完fetch之后把取回的數(shù)據(jù)賦值給f,然后再把f打印出來,這個看起來很像同步的寫法,但是實現(xiàn)起來卻是異步的。

是不是很簡單,如果用回掉函數(shù)或者Promise的寫法會很復(fù)雜的。

let a = asyncFun()
a.next()

a.value.then(function(data){
  return data.json();
}).then(function(data){
  g.next(data);
});

這樣的寫法表示起來很簡潔,但是流程管理比較復(fù)雜。

Thunk函數(shù)

thunk函數(shù)是自動執(zhí)行Generator函數(shù)的一種方法。

Thunk函數(shù)的核心理解就是傳名調(diào)用。

function f(x){
    return x * 2
}

f(x + 6)

//等同于

var thunk = function(x) {
    return x + 5
}

function f() {
    return thunk() * 2 
}

理論上,x+6被thunk函數(shù)替代了,所有用到原來參數(shù)的地方,直接用thunk求值就行。

這就是Thunk函數(shù)的策略,是傳名求值的一種實現(xiàn)策略,用來替換某個表達式。

js中的Thunk函數(shù)

在js中,函數(shù)的參數(shù)并不是傳名的而是傳值的,所以,thunk函數(shù)不是用來替換表達式的,而是用來替換多參數(shù)函數(shù)的。將其中一個參數(shù)替換成只接收一個回掉函數(shù)的單參數(shù)參數(shù)。

聽起來很拗口,看代碼。

// 正常的寫法
fs.readFile(filename,callback);

// thunk函數(shù)的單參數(shù)版本
var thunk = function(filename) {
    return function(callback) {
        return fs.readFile(filename,callback);
    }
}

var readThunk = thunk(filename)
readThunk(callback)

理論上,只要函數(shù)的一個參數(shù)是回調(diào)函數(shù),就可以改寫成Thunk函數(shù)。

Thunkify模塊

一個轉(zhuǎn)換器,把函數(shù)轉(zhuǎn)成Thunk函數(shù)

安裝
npm install thunkify

使用方法:
var thunkify = require("thunkify");
var fs = require("fs");

var read = thunkify(rs.readFile);
read("package-json")(function(err,str)
    // ...
)

thunkify接受一個回調(diào)方法、

Generator函數(shù)的流程管理

之前說過,Generator函數(shù)的流程管理比較復(fù)雜,那么Thunk函數(shù)有什么用呢,正確答案是,他可以幫助Generator函數(shù)實現(xiàn)自動的流程管理。

function* gen(){
    // ...
}
var g = gen();
var res = g.next();

while(!res.done){
    console.log(res.value)
    res.next();
}

理論上,上面的代碼可以實現(xiàn)自動執(zhí)行,但是,不能適合異步。用Thunk可以解決這個問題。

var thunkify = require("thunkify");
var fs = require("fs");
var readFileThunk = thunkify(fs.readFile)

var gen = function* (){
    var r1 = readFileThunk("filename1")
    console.log(r1);
    var r2 = readFileThunk("filename2")
    console.log(r2);
    
}
Thunk函數(shù)的自動流程管理

Thunk函數(shù)的真正意義在于可以自動執(zhí)行Generator函數(shù),看下邊的例子。

function* g(){
    // ...
}

function run(fn){    //Thunk函數(shù)接收一個Generator函數(shù)
    var gen = fn();
    
    function next(err,data){
        var result = gen.next(data);
        if(result.done) return;
        return result.value(next)
    }
    
    next();
}

run(g)

解析一下這個代碼:
run方法其實就是一個Generator函數(shù)自動執(zhí)行器。內(nèi)部函數(shù)next就是Thunk的回調(diào)函數(shù),next函數(shù)首先把Generator函數(shù)的指針指向Generator函數(shù)的下一步方法(gen.next()),如果沒有,就把next函數(shù)傳給Thunk函數(shù)(result.value屬性),否則直接退出。

有了這個執(zhí)行器,執(zhí)行Generator函數(shù)就方便多了,不管內(nèi)部多少操作,直接把Generator函數(shù)傳給run函數(shù)即可,當然前提是每一個異步操作都是一個Thunk函數(shù),也就是yield后面的必須是Thunk函數(shù)。

function* g(){
    var f1 = yield fs.readFileThunk("filename1")
    var f2 = yield fs.readFileThunk("filename2")
    ...

}

run(g)

Thunk 函數(shù)并不是 Generator 函數(shù)自動執(zhí)行的唯一方案。因為自動執(zhí)行的關(guān)鍵是,必須有一種機制,自動控制 Generator 函數(shù)的流程,接收和交還程序的執(zhí)行權(quán)。回調(diào)函數(shù)可以做到這一點,Promise 對象也可以做到這一點。

這篇文章寫得比較難懂,其實主要是為了下一篇文章做鋪墊。

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

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

相關(guān)文章

  • ES6&ES7中的異步async函數(shù)

    摘要:更好的語義和分別表示異步和等待,比起和更容易理解。前邊聲明關(guān)鍵字,表示內(nèi)部有內(nèi)部操作,調(diào)用函數(shù)會返回一個對象。等價于其中函數(shù)就是自動執(zhí)行器。 async函數(shù) 定義 async函數(shù)其實就是之前說過的Generator的語法糖,用于實現(xiàn)異步操作。它是ES2017的新標準。 讀取兩個文件: const fs = require(fs) const readFile = function(f...

    dongxiawu 評論0 收藏0
  • ES6&ES7中的異步Generator的語法

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

    djfml 評論0 收藏0
  • ES6-7

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

    mudiyouyou 評論0 收藏0
  • ES6 Generator異步的同步書寫

    摘要:返回值是一個對象,它的第一個屬性是后面表達式的值或者的值第二個屬性表示函數(shù)是否執(zhí)行完成。真正的業(yè)務(wù)邏輯確實是用同步的方式寫的。 開始前 我們從來沒有停止過對javascript語言異步調(diào)用方式的改造,我們一直都想用像java那樣同步的方式去寫異步,盡管Promise可以讓我們將異步回調(diào)添加到then方法中,但是這種調(diào)用方式仍然不那么優(yōu)雅,es6 中新增加了generator,我們可以通...

    andycall 評論0 收藏0
  • Promise & Generator——幸福地用同步方法寫異步JavaScript

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

    Harpsichord1207 評論0 收藏0

發(fā)表評論

0條評論

venmos

|高級講師

TA的文章

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