如果执行异步操作,将产生表达式块

Will yield expression block if execute asynchronous operation?

本文关键字:表达式 执行 异步操作 如果      更新时间:2023-09-26

我已经了解到,当我们调用next()时,代码将继续运行,直到yield关键字,并且next()返回将保持此值。我的问题是,如果yield表达式正在进行异步操作,例如执行文件io或http请求,并且在异步调用完成之前,我们调用next,代码是否仍然会阻塞,或者立即恢复运行,即使异步操作尚未完成?,为什么?

function * generator(){
  yield http.get('http://google.com');
  yield http.get('http://yahoo.com');
}
var gen = generator();
var a = gen.next();
var b = gen.next(); 

如果google.com的请求还没有完成,yahoo.com的请求会立即发送吗?或者它必须阻止并等待谷歌的请求完成?

如果您使用的方法"get"是异步的,它将立即返回(非阻塞)。这意味着即使google.com还没有完成,yahoo.com的请求也会被发送。

您发布的代码将不会等待每个http.get请求执行。但是,可以通过改变生成器的使用方式来实现这一点。

下面的代码展示了如何使用回调和生成器实现异步睡眠函数:

function wait(ms) {
    return function (cb) {
        setTimeout(cb, ms);
    };
}
function * generator(startTime) {
    console.log('start ' + (Date.now() - startTime));
    yield wait(1000);
    console.log('stop ' + (Date.now() - startTime));
}
console.log("Using generator asynchronously")
var gen2 = generator(Date.now());
gen2.next().value(function () {
    gen2.next();
});

然而,仍然可以忽略回调并使yield立即返回。

console.log("Using generator synchronously")
var gen1 = generator(Date.now());
gen1.next();
gen1.next();

对于你发布的代码,让http.get返回Promise是最有意义的。在这种情况下,你可以有类似这样的代码:

function * generator(){
    var google = yield http.get('http://google.com');
    var yahoo = yield http.get('http://yahoo.com');
}
var gen = generator();
loop(gen);
function loop(gen, next) {
    var result = gen.next(next);
    if (!result.done) {
        result.value.then(function (value) {
            loop(gen, value)
        });
    }
}