需要进一步帮助使javascript同步生成器处理异步函数

时间:2016-11-10 16:28:55

标签: javascript iterator generator

我是Node JS的新手。我需要同步调用异步函数(http request())。凯莉辛普森的This文章给了我很多帮助;特别是这个代码位正是我所需要的:

function request(url) {
    // this is where we're hiding the asynchronicity,
    // away from the main code of our generator
    // `it.next(..)` is the generator's iterator-resume
    // call
    makeAjaxCall( url, function(response){
        it.next( response );
    } );
    // Note: nothing returned here!
}

function *main() {
    var result1 = yield request( "http://some.url.1" );
    var data = JSON.parse( result1 );

    var result2 = yield request( "http://some.url.2?id=" + data.id );
    var resp = JSON.parse( result2 );
    console.log( "The value you asked for: " + resp.value );
}

var it = main();
it.next(); // get it all started

但是我需要更进一步:我需要能够将 result1 传递给另一个函数(下面的例子中的processResult()),然后如果某些条件会调用request()满足了。像这样:

function request(url) {
    makeAjaxCall( url, function(response){
        it.next( response );
    } );
}

function processResult(resSet) {
    if (resSet.length>100)
        return request("http://some.url.1/offset100");
    else
        write2File(resSet);
}

function *main() {
    var result1 = yield request( "http://some.url.1" );
    processResult(result1)
}

var it = main();
it.next();

但是当我尝试这样做时,request("http://some.url.1/offset100")不会返回任何值。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

  

但是当我尝试这样做时,request("http://some.url.1/offset100")   不会返回任何值。

生成器函数与任何其他函数一样执行,除非使用yield暂停它。

您对function processResult(resSet){}的来电是同步通话,在异步function *main() {}完成之前返回function request(url) {}。您需要在生成器函数内部继续调用异步function request(url){}。您可以通过以这种方式重构代码来实现此目的:

function processResult(resSet) {
    if (resSet.length>100)
        return true;
    else
        write2File(resSet); // assuming that this function is synchronous
        return false; // not necessary as the function in this case returns `undefined` by default which coerces to false - but it illustrates the point
}

function *main() {
    var result1 = yield request( "http://some.url.1" );
    if(processResult(result1)) {
        var offset100 = yield request("http://some.url.1/offset100");
    }

    // do something with offset100

var it = main();
it.next();