Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/410.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将无限for循环中的wait转换为原始promise.then_Javascript_Promise_Ecmascript 2017 - Fatal编程技术网

Javascript 将无限for循环中的wait转换为原始promise.then

Javascript 将无限for循环中的wait转换为原始promise.then,javascript,promise,ecmascript-2017,Javascript,Promise,Ecmascript 2017,据我所知,async/await只是承诺之上的语法糖分。考虑这个代码片段: function sleep(n){ return new Promise(res => setTimeout(res, n)); } function* range(n){ var i = 0; while(i < n) yield i++; } async/await使代码非常线性、高效且易于理解。需要记住的一点是,range不一定要有一个实际的目的才能起作用 现在的问题

据我所知,
async/await
只是
承诺之上的语法糖分。考虑这个代码片段:

function sleep(n){
    return new Promise(res => setTimeout(res, n));
}

function* range(n){
    var i = 0;
    while(i < n)    yield i++;
}
async/await
使代码非常线性、高效且易于理解。需要记住的一点是,
range
不一定要有一个实际的目的才能起作用

现在的问题是,如何使用ES7之前时代的
承诺来重写这一点。下面是同一循环的可能实现:

function doStuff(){
    return Array.from(range(10)).reduce((acc, ele) => {
        return acc
            .then(() => console.log(ele))
            .then(() => sleep(1000))
    }, Promise.resolve());
}
忽略代码不是很优雅的事实,使用
Array.from(range(10))

  • 创建不需要的额外数组,并且
  • 假设
    范围(10)
    将在未来某一点结束
  • 看起来不是一个好的转换

    我们也可以通过使用
    yield
    作为
    wait
    来彻底改造轮子,但这会使语法不符合ES5。这里的目标是:

  • 使用符合ES5的语法重写
  • 使用“睡眠”功能
  • 动态链接
    sleep
    承诺,同时允许迭代器没有结束
  • doStuff
    可以链接:

    doStuff().finally(cleanUp);  // clean up if something failed
    
  • (可选)代码不应过于复杂


  • 有什么想法吗?

    我认为下面的方法可以解决这个问题,您的示例没有显示如何处理resolve值以及它与迭代器值的关系,因此我更改了如何调用sleep

    某些promise polyfil可能会使用高promise链耗尽堆栈空间,因此您应该检查您的polyfil(如果其实现返回并继续执行设置超时,则堆栈应清除,但某些polyfil可能不会以这种方式实现)

    功能睡眠(n){
    返回新承诺(res=>setTimeout(=>res(n/100),n));
    }
    功能*范围(n){
    var i=0;
    而(i{
    console.log(“解析为:”,解析);
    //如果(resolve==3){抛出“nope”;}
    返回睡眠(分辨率*100);
    },
    rec=(p,iter)=>{
    const result=iter.next();
    如果(结果完成){
    返回p;
    }
    p=p.then(=>processValue(result.value))
    返回p(
    解析=>{
    返回记录(p,iter)
    }
    );
    },
    iter=范围(10),
    firstResult=iter.next();
    if(firstResult.done){
    返回processValue(firstResult.value);
    }
    返回rec(processValue(firstResult.value),iter);
    }
    多斯塔夫()
    .那么(
    x=>console.log(“完成:”,x)
    ,拒绝=>console.warn(“失败:”,拒绝)
    
    );我一直说,如果需要异步设计模式,请首先查看库。在本例中,由于您正在使用Promissions,请查看promisified库。翻译是直截了当的:

    var n = 0;
    async.whilst(() => n < 10, () => {
        n++;
        console.log(n);
        return sleep(1000);
    })
    
    var n=0;
    异步时(()=>n<10,()=>{
    n++;
    控制台日志(n);
    返回睡眠(1000);
    })
    
    @zerkms
    范围可以达到它想要的高度,而
    for
    循环仍然可以工作,而
    数组。from
    将冻结。您是否尝试过使用transpiler查看它会输出什么?如果您从
    中删除
    数组并使用循环会怎么样?啊哈,问题的关键是范围的大小:p我明白了now@zerkms但这不是一个准确的翻译。异常可以在主体中抛出(即
    console.log
    所在的范围),在构建承诺链时,您无法提前知道。
    var n = 0;
    async.whilst(() => n < 10, () => {
        n++;
        console.log(n);
        return sleep(1000);
    })