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

时间:2016-12-07 15:06:34

标签: javascript promise es6-promise

我有一个承诺返回函数,可以执行一些异步操作,我们称之为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!");
})

这成功地束缚了我的承诺(或者接缝,我在控制台中每秒得到一个“解决!”)。 然而.then()我尝试在第一个承诺结束后repeatFunction(5)之后发生链接,而不是在所有5个结束之后!

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

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

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

8 个答案:

答案 0 :(得分:4)

简单地说:

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 :(得分:3)

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

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

如果您有then,但没有返回任何内容,那么它只会解决上层承诺。这就是发生的事情。

答案 2 :(得分:1)

致电PlacePhototTVC

时,您错过了appCapabilities.SetCapability("app", pathToApp);
return

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

答案 3 :(得分: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

这是垃圾桶。您仅限于使用副作用函数作为f的{​​{1}}参数。因此,登录到控制台可以正常工作,但如果你真的想用这个值做什么呢?

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

粗体的重要变化)

asyncDouble

答案 4 :(得分:0)

您可能会发现relign对此类事情很有用。以下是您使用relign series和relign setTimeout编写的示例。

const fnToRepeat = () =>
  relign.setTimeout(() => console.log("resolved!"), 1000);

relign.series((new Array(5)).fill(fnToRepeat))
  .then(() => console.log('done'));

答案 5 :(得分:0)

我想要类似的东西,所以我在(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!")
}) 

答案 6 :(得分:0)

const http = require('http');
const https = require('https');
const { t, d, r } = require('minimist')(process.argv.slice(2));

const checkRoot = config => {
  const { delaySeconds, rootUrl } = config ? config : { delaySeconds: 6 };
  const delay = delaySeconds * 1000;
  const protocolString = rootUrl.split(':')[0];
  const protocol = {
    http: http,
    https: https,
  };
  return new Promise(res => {
    setTimeout(() => {
      protocol[protocolString]
        .get(rootUrl, resp => {
          let data = '';
          resp.on('data', chunk => {
            data += chunk;
          });
          resp.on('end', () => {
            res({ success: data.includes('<!doctype html>') });
          });
        })
        .on('error', err => {
          console.log(`Error: ${err.message}`);
          res({ success: false });
        });
    }, delay);
  });
};
const repeatChecking = async ({ times, delaySeconds, rootUrl }) => {
  let isReady = false;
  console.log(
    `will try ${times}, and with ${delaySeconds} seconds delay in between for ${rootUrl}`
  );
  let i = 1;
  while (i <= times) {
    if (isReady === true) {
      break;
    }
    const res = await checkRoot({ delaySeconds, rootUrl }).then();
    isReady = res.success;
    console.log(`testing ${i}, status: root ready => ${res.success}`);
    i++;
  }
  if (isReady) {
    console.log('Done, root is ready');
    return;
  }
  process.stdout.write('ERROR: root could not be reached\n');
  process.exit(1);
};

repeatChecking({ times: t, delaySeconds: d, rootUrl: r });

答案 7 :(得分:-1)

let loopP = (n, f, ...args) => {
  let p = f(...args);
  p.then(res => {
    if (n - 1) {
      loopP(n - 1, f, res);
    }
  });
};

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

例如......

let addOneP = i => {
  console.log(i + 1);
  return Promise.resolve(i + 1);
};

loopP(5, addOneP, 0);
// logs:
// 1
// 2
// 3
// 4
// 5