ES6:在异步调用中使用生成器

时间:2016-04-27 09:21:29

标签: javascript asynchronous ecmascript-6 generator let

我读过David Walsh关于在异步任务中使用生成器的文章(https://davidwalsh.name/async-generators),我想做同样的事情。 这是我的代码:

function request(time) {
    let rand = Math.random()*10;
    console.log(`rand is ${rand}`);
    setTimeout(function(rand){
        it.next(rand)
    }, time);
}

function *main() {
    let result1 = yield request(5);
    result1 = parseInt(result1);
    let result2 = yield request(result1);

    console.log(`result1 is ${result1} and result2 is ${result2}`);
}

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

但在控制台我可以看到

rand is 6.367766260304355
rand is 0.3009188563265597
result1 is NaN and result2 is undefined

据我所知,当脚本到达时,让rand = Math.random()* 10第一次将值保存在rand中,但是它会转到setTimeout但不会进入但是到达it.next()at脚本的结尾然后返回到setTimeout的内部,但是这次rand是未定义的。 这是为什么?如何保留rand的值并将其传递给result1?

编辑: 好的,当我编辑

function request(time) {
    setTimeout(function(){
        let rand = Math.random()*10;
        console.log(`rand is ${rand}`);
        it.next(rand)
    }, time);
}

它工作正常。似乎我无法将值传递给setTimeout ......为什么?

2 个答案:

答案 0 :(得分:3)

您可以将参数传递给由计时器调用的函数,但不是您尝试的方式。

您需要将这些参数传递给setTimeout itself

var timeoutID = window.setTimeout(func, [delay, param1, param2, ...]);


function request(time) {
    let rand = Math.random()*10;
    console.log(`rand is ${rand}`);
    setTimeout(function(rand){
        it.next(rand)
    }, time, rand);
}

但在你的情况下没有必要。您可以在内部函数范围内访问rand

function request(time) {
    let rand = Math.random()*10;
    console.log(`rand is ${rand}`);
    setTimeout(function(){
        it.next(rand); 
    }, time);
}

答案 1 :(得分:1)

您的代码中有两个rand个变量:

let rand = Math.random()*10;
//  ^^^^
…
setTimeout(function(rand) {
//                  ^^^^
    …
}, time);

该函数的参数声明第二个变量,该变量将从外部作用域中隐藏一个变量。由于回调函数未传递任何参数,因此其值为undefined - 这就是您传递给next的内容。

请勿声明该参数,并且可以通过关闭在回调中使用外部rand