首页 文章

Javascript Promises:链接相同的承诺n次,然后做其他事情

提问于
浏览
4

我有一个承诺返回函数,它做了一些异步的东西,让我们称之为 functionToRepeat() .

我正在尝试编写函数 repeatFunction(amount) ,以便它将启动承诺,等待完成,再次启动它,等待完成,等等一定时间 . 这 repeatFunction(amount) 也应该是可以的,以便我可以在执行后链接其他东西 .

这是我的尝试:

function functionToRepeat(){
  let action = new Promise(function(resolve,reject){
    setTimeout(function(){
      console.log("resolved!");
      resolve()}
    ,1000);
  })
  return action
}

function repeatFunction(amount) {
  if(amount==0){
    return Promise.resolve();
  }
  return functionToRepeat().then(function(){
    repeatFunction(amount-1);
  });
}

repeatFunction(5).then(function(){
 console.log("DONE!");
})

这成功地链接了我的承诺(或者接缝,我在控制台中每秒得到一个"resolved!") . 然而_1124175_我试图在我的 repeatFunction(5) 发生在第一个承诺结束后发生,而不是在所有5个结束之后!

所以在我的控制台中,我得到:

解决! DONE!解决!解决!解决!解决!

我做错了什么,我应该改变什么?

7 回答

  • 3

    我认为你几乎就在那里,但是你必须在你的函数的then块中再次返回repeatFunction来重复 .

    return functionToRepeat().then(function(){
        return repeatFunction(amount-1);
      });
    }
    

    如果你有 then ,但不返回任何东西,那么它只会解决上层承诺 . 这就是发生的事情 .

  • 0

    怎么样简单:

    function repeat(func, times) {
      var promise = Promise.resolve();
      while (times-- > 0) promise = promise.then(func);
      return promise;
    }
    

    用这个测试:

    function oneSecond() {
      return new Promise(function (resolve, reject) {
        setTimeout(function () {
          console.log("tick");
          resolve();
        }, 1000);
      });
    }
    
    repeat(oneSecond, 5).then(function () {
        console.log("done");
    });
    

    此输出产生超过5秒:

    tick
    tick
    tick
    tick
    tick
    done
    
  • 1

    当你拨打 repeatFunction(amount-1) 时,你错过了 return

    function functionToRepeat(){
      let action = new Promise(function(resolve,reject){
        setTimeout(function(){
          console.log("resolved!");
          resolve()}
        ,1000);
      })
      return action
    }
    
    function repeatFunction(amount) {
      if(amount==0){
        return Promise.resolve();
      }
      return functionToRepeat().then(function(){
        return repeatFunction(amount-1); // Added return
      });
    }
    
    repeatFunction(5).then(function(){
     console.log("DONE!");
    })
    

    https://plnkr.co/edit/93T6B4QkBv0mYS4xPw0a?p=preview

  • -1

    你可能会发现relign对这类事情很有用 . 这是你用relign series和relign setTimeout写的例子 .

    const fnToRepeat = () =>
      relign.setTimeout(() => console.log("resolved!"), 1000);
    
    relign.series((new Array(5)).fill(fnToRepeat))
      .then(() => console.log('done'));
    
  • 2

    我想要类似的东西,所以我在(https://repl.it/@turlockmike/BriskLovableLinuxkernel)写了一个通用函数

    function repeat(fn, times) {
      if (times == 1) {
        return fn()
      } else {
        return new Promise(function(resolve, reject) {
          return fn().then(function() {
            return resolve(repeat(fn,times - 1))
          })
        })
      }
    }
    

    用法

    function doSomething() {
      return new Promise(function(resolve, reject) {
         //do something interested here
         setTimeout(function(){
           console.log("resolved!");
           resolve()}
         ,1000);
      })
    }
    
    repeat(doSomething, 5).then(() => {
      console.log("all Done!")
    })
    
  • 1

    你可以使用 async / await 和一个简单的 while 循环 . 这使您保持Asyncland允许您在重复功能完成后继续链接

    async function asyncRepeat (f, n) {
      while (n-- > 0)
        await f()
    }
    
    asyncRepeat(functionToRepeat, 5).then(() => {
      console.log('done')
    })
    
    // some value
    // some value
    // some value
    // some value
    // some value
    // done
    

    这是垃圾桶 . 您只能使用副作用函数作为 asyncRepeatf 参数 . 因此,登录控制台可以正常工作,但如果您真的想要使用该值执行某些操作,该怎么办?

    这是对 asyncRepeat 的更新,它允许您通过重复应用输入函数来线程化值(在此示例中为 asyncDouble

    bold 中的重要变化)

    async function asyncRepeat (f, n, x) {
      while (n-- > 0)
        x = await f(x)
      return x
    }
    
    function asyncDouble (x) {
      return new Promise(function (resolve, reject) {
        setTimeout(() => {
          console.log('x is currently: %d', x)
          resolve(x * 2) // resolve an actual value
        }, 1000)
      })
    }
    
    asyncRepeat(asyncDouble, 5, 2).then(result => {
      console.log('result: %d', result)
    })
    
    // x is currently: 2
    // x is currently: 4
    // x is currently: 8
    // x is currently: 16
    // x is currently: 32
    // result: 64
    
  • 0
    let loopP = (n, f, ...args) => {
      let p = f(...args);
      p.then(res => {
        if (n - 1) {
          loopP(n - 1, f, res);
        }
      });
    };
    

    其中 n 是迭代次数, f 是要调用的Promise返回函数 . 对 f 的每次连续调用在结算时都会传递上一次调用的结果 .

    例如...

    let addOneP = i => {
      console.log(i + 1);
      return Promise.resolve(i + 1);
    };
    
    loopP(5, addOneP, 0);
    // logs:
    // 1
    // 2
    // 3
    // 4
    // 5
    

相关问题