繁体   English   中英

如何同步Promise对象?

[英]How To Synchronise Promise Objects?

我有承诺需要同步的对象。 例如,第二个承诺在第一个承诺完成之前不应该起作用。 如果第一个拒绝,则必须再次执行。

我已经实现了一些例子。这个很好用。 调用getVal,等待2000ms,返回,i ++,再次调用getVal .....

 getVal() {
       return new Promise(function(resolve, reject) {
      setTimeout(function(){ resolve(19) }, 2000);
         });

     }

async promiseController(){

    for(var i =0;i<5;i++)
      {
        var _val = await this.getVal()
        console.log(_val+'prom');
      }
    }

但我需要控制一组promise对象。 我想要做的是我有一个数据,我把它分成5块。 在处理完第一部分(例如:发送到服务器)后,我想要处理第二部分,否则我必须再次处理第一部分。

这是我制作的原型实现

  getVal() {
   return new Promise(function(resolve, reject) {
  setTimeout(function(){ resolve(19) }, 2000);
     });

 }

async promiseController(){
  var proms=[]
  for(var i =0;i<5;i++)
    {
      proms.push(this.getVal())
    }

for(var i =0;i<5;i++)
  {
    var _val = await proms[i]
    console.log(_val+'prom');
  }
}

此代码中的Promises对象按顺序工作。 我如何修复下面的代码,以便它作为第一个例子同步工作。

async promiseController(){
  for(const value of array) {
    console.log((await this.getVal(value))+'prom');
  }
}

无需过度复杂化。 只需在循环中调用await ,它就会等待你想要的东西。

正如另一个答案所说的那样 - 承诺代表一种价值,而不是一种操作。 对于操作,使用常规功能。

如果你想忽略失败,你可以在.catch(() => {}) 如果要重试直到失败 - 您可以重构重试函数并使用它:

const retry = fn => (...args) => fn(...args).catch(retry(fn));

如果您的目标是在第一个承诺解决之前不“执行后续承诺”,那么您需要记住,承诺代表已经在飞行中的异步活动。 一旦承诺存在,就为时已晚。

在第一个promise完成之前,您需要不要调用后续的promise工厂方法。 您的第一个示例通过在上一个promise完成之前不调用getVal()完成此操作。

所以你最终得到的结果如下:

delay(time) {
    return new Promise(resolve => setTimeout(resolve, time));
}

async promiseController() {
    const factories = [];
    for (let i = 0; i < 5; ++i) {
        factories.push(() => this.getVal());
    }

    for (const f of factories) {
        // keep running this factory until it succeeds
        let success = false;
        while (!success) {
            try {
                const promise = f();
                const result = await f;
                success = true;
                console.log(`result = ${result}`);
            }
            catch (err) {
                console.log("promise failed.  retrying");
                await delay(100);
            }
        }
    }
}

你可以使用递归,命名函数, .then()

 var arr = [Promise.resolve("a") , Promise.resolve("b") , Promise.resolve("c")]; var i = 0; var res = []; function foo() { // conditional resolved or rejected promise var n = String(new Date().getTime()).slice(-1); // if `n` < 5 reject `n` , else resolve `n` var curr = n < 5; return curr ? arr[i] : Promise.reject(["rejected", n]) } var p = (function repeat() { var promise = foo(); return promise .then(function(data) { console.log(data); res.push(data); ++i; if (i < arr.length) return repeat() // return `res` array when all promises complete else return res }) .catch(function(err) { console.log(err); if (err[0] === "rejected") return repeat() }) }()); p.then(function(complete) { console.log("complete:", complete) }); 

好吧 我相信为了正确的函数编程目的,应避免使用asyncawait thingy。 我相信承诺非常充足。 然而,如果您想继续使用C ++进行编码,那么asyncawait适合您。

我有承诺需要同步的对象。 例如,第二个承诺在第一个承诺完成之前不应该起作用。 如果第一个拒绝,则必须再次执行。

让我简单介绍下面的代码。 我们有async()函数,它接受数据和回调(错误优先类型)。 至于演示目的,它将尝试在2000ms内使用数据调用回调,但是在1000ms处有超时。 所以50-50它将调用带有数据或错误的回调。

所以我们实际上需要它给我们一个承诺,所以我在promisify()的帮助下promisify()它,它需要async()函数并返回asyncPro()函数。 这实际上与async()相同,但返回一个promise。 所以我们期望在then阶段使用我们的回调。

然后是tryNTimes(data,asyncFun,n = 5)函数,它接受数据,一个promisified异步函数和一个整数,指定在拒绝它之前尝试的次数。 它的默认尝试次数为5,但您可以通过传递第三个参数将其设置为任何值。

至于最后一部分,我们有了flowControl() ,它在Array.prototype.reduce()的帮助下完美地链接了我们的promise。

所以现在我们将所有的承诺一个接一个地链接起来,在尝试5次之前没有一个会失败。

 function promisify(fun){ return (data) => new Promise((resolve,reject) => fun(data, (err,res) => err ? reject(err) : resolve(res))); } function async(data, callback){ var dur = Math.floor(Math.random()*2000); setTimeout(_ => callback(false,data),dur); // may resolve before timeout setTimeout(_ => callback("error at " + data),1000); // timeout at 1 sec } function tryNTimes(data,asyncFun,n = 5){ return new Promise((resolve,reject) => { n === 0 && reject("try out fail at 5 tries: " + data); asyncFun(data).then(v => resolve("resolved at countdown " + n + ": " + v)) .catch(e => resolve(tryNTimes(data,asyncFun,--n))); }); } function flowControl(d,f,tc){ return d.reduce((prom,chunk) => prom.then(v => { console.log(v); return tryNTimes(chunk,f,tc); }),Promise.resolve("initial dummy promise")); } var data = ["chunk_1", "chunk_2", "chunk_3", "chunk_4", "chunk_5"], asyncPro = promisify(async); // now our async function returns a promise flowControl(data,asyncPro).then(v => console.log(v)) .catch(e => console.log(e)); 

如果您希望更频繁地看到“5次尝试”错误,请降低async()函数中的超时值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM