将无限for循环中的await转换为raw promise.then

时间:2017-12-03 23:40:35

标签: javascript promise ecmascript-2017

据我所知,static只是async/await的语法糖。请考虑以下代码段:

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

function* range(n){
    var i = 0;
    while(i < n)    yield i++;
}

async function doStuff(){ for(let n of range(10)){ console.log(n); // print the number await sleep(1000); // wait for 1 second } } 使代码非常线性,高效且易于理解。要记住的一件事是async/await没有必要实际结束这一点。

现在的问题是如何使用pre-ES7时代range重写它。这是同一循环的可能实现:

promise.then

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

  1. 创建一个不需要的额外数组,并且
  2. 假设Array.from(range(10))将在未来结束某些方面。
  3. 看起来不是一个好转换。

    我们也可以使用range(10)作为yield完全重新发明轮子,但这会使语法不符合ES5。这里的目标是:

    1. 使用符合ES5的语法重写
    2. 使用承诺返回await函数
    3. 动态链接sleep承诺,同时允许迭代器没有结束
    4. sleep可以链接:

      doStuff
    5. (可选)代码不应过于复杂

    6. 有什么想法吗?

2 个答案:

答案 0 :(得分:1)

我认为以下内容可能会起作用,您的示例不会显示如何处理解析值以及它与迭代器值的关系,因此我对睡眠的调用方式进行了更改。

一些承诺polyfils可能会耗尽具有高承诺链的堆栈空间,所以你应该检查你的polyfil(如果它的实现返回并继续使用setTimeout,堆栈应该清除,但是一些polyfils可能不会以这种方式实现它。)

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

    function* range(n){
      var i = 0;
      while(i < n)    yield i++;
    }

    function doStuff(){
      const processValue = 
        resolve => {
          console.log("resolved with:",resolve);
          // if(resolve===3){throw "nope";}
          return sleep(resolve*100);
        },
      rec = (p,iter) => {
        const result = iter.next();
        if (result.done){
          return p;
        }
        p = p.then(_=>processValue(result.value))
        return p.then(
          resolve=>{
            return rec(p,iter)
          }
        );
      },
      iter = range(10),
      firstResult = iter.next();
      if(firstResult.done){
        return processValue(firstResult.value);
      }
      return rec(processValue(firstResult.value),iter);
    }

    doStuff()
    .then(
      x=>console.log("done:",x)
      ,reject=>console.warn("fail:",reject)
    );

答案 1 :(得分:1)

我总是说如果你需要异步设计模式,首先要看async库。在这种情况下,由于您正在使用promises,请查看promisified async-q库。翻译很简单:

var n = 0;
async.whilst(() => n < 10, () => {
    n++;
    console.log(n);
    return sleep(1000);
})