ES6 异步编程之三:Generator续

媒介

《ES6 异步编程之一:Generator》中完成了一个异步函数挪用链,它是一个顺序挪用链,很相似义务链情势,但实际每每不是平淡无奇的,更多的实际上是峰回路转,本文将继承议论更多Generator的用法。

作为函数的Generator

在之前的示例中,我们更多的是把天生器作为一个迭代器来轮回挪用每一个函数,但无视了天生器也是个函数,意味着天生器内部可以完成庞杂的营业逻辑,以下的代码经由过程yield守候文件读取效果并对效果举行特定的处置惩罚,


    function* generator() {
        let r1 = yield get('a');
        if (r1) {
            let r2 = yield get('b');
            if (r2) {
                console.log(yield get('d'));
            }
        } else {
            console.log(yield get('c'));
        }
    }
    
    let g = generator();
    g.next();

假如get是个异步挪用,以上的代码想要可以实行则须要get函数实行获得效果后挪用天生器的next要领来推动,这请求get函数能持有天生器对象,这明显并不轻易。

偏函数

偏函数(Partial Function)是对函数定义域的子集定义的函数,情势上就是指定恣意部份参数天生一个新的函数,以下:

    function sum(a, b, c) {
        return a + b + c;
    }
    
    function sum1(a) {
        return function(b, c) {
            return a + b + c;
        };
    }
    
    function sum2(a, b) {
        return function(c) {
            return a + b + c;
        };
    }
    
    sum(1, 2, 3) == sum1(1)(2, 3); //true
    sum(1, 2, 3) == sum2(1, 2)(3); //true

平常在设想异步挪用api时,我们老是声明一个参数来吸收回调函数,当和偏函数相结合就变成如许:

    function get(f, callback) {
        delay(100, function(s) {
            callback(s + ':get ' + f);
        });
    }
    
    get('a', func);  //挪用get时必需马上传入一个函数
    
    //转换成偏函数情势:
    function partialGet(f) {
        return function(callback) {
            delay(100, function(s) {
                callback(s + ':get ' + f);
            });
        };
    }
    
    let pGet = partialGet('a');   //可以先天生一个函数
    pGet(func);  //须要时再传入回调函数实行

从上面的例子中可以发明,偏函数能使定义和实行星散,说来巧了,天生器可用于定义营业逻辑而天生器的next用于推动营业实行,两者也是互相星散的。

天生器和偏函数

基于前面这么多铺垫,假定get就是一个偏函数,以下:

    function get(f) {
        return function(callback) {
            delay(100, function(s) {
                callback(s + ':get ' + f);
            });
        };
    }

这意味着,yield get('a')使得next函数实行的效果其value属性值是个函数,该函数的参数是一个能吸收get异步效果的回调函数,即:

    g.next().value(function(value) {
        g.next(value); //value成为yield的返回并继承推动营业逻辑
    });

经由过程递归可以不停的实行天生器的next要领,一个全新的经由过程天生器来完成营业逻辑的run要领便呼之欲出了,


function run(gen) {
    let g = gen();

    function next(lastValue) {
        let result = g.next(lastValue); //将上一个异步实行效果传出给当前的yield并实行下一个yield
        if (result.done) {
            return result.value;
        }
        //value是偏函数返回的新函数,它的参数是个用来吸收异步效果的回调函数
        result.value(next);  //next作为吸收异步效果的回调函数
    }

    next();
}

run(generator);

综合以上例子不难发明别的一个优点,经由过程偏函数可以使异步挪用api不受天生器的侵入,《ES6 异步编程之一:Generator》中完成的异步挪用须要将天生器作为参数,有兴致的话你可以尝试革新一下之前的示例。

如今经由过程新编写的run函数便可以来实行本文一开始编写的谁人天生器了。

thunkify

偏函数的计划对api和天生器也是有侵入的,他请求:

  1. api必需是偏函数情势;

  2. 天生器定义营业逻辑,每一个yield 背面的函数必需是挪用偏函数;

第二个题目是本计划的中心机制所请求,但第一个题目我们可以经由过程thunkify来处理,api照旧根据get(value, callback)体式格局定义,但定义天生器时须要将异步api挪用经由过程thunkify转换为偏函数,以下:

    let Thunkify = require('thunkify');
    
    let thunkifiedGet = Thunkify(get);
    
    function get(f, callback) {
        delay(100, function(s) {
            callback(s + ':get ' + f);
        });
    
    }
    
    function* generator() {
        let r1 = yield thunkifiedGet('a');
        if (r1) {
            let r2 = yield thunkifiedGet('b');
            if (r2) {
                console.log(yield thunkifiedGet('d'));
            }
        } else {
            console.log(yield thunkifiedGet('c'));
        }
    }
    原文作者:码农彭盛
    原文地址: https://segmentfault.com/a/1190000008326347
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞