代码之家  ›  专栏  ›  技术社区  ›  David Schumann Axnyff

同步多个承诺,同时允许多次重试

  •  0
  • David Schumann Axnyff  · 技术社区  · 8 年前

    我试图建立一个下载自动重试下载。基本上是一个任务队列,它重试任务一定次数。我第一次尝试使用 Promise.all() described here 没有帮助(并且是一个反模式,如该线程中进一步描述的)

    所以我有一个版本的工作,似乎有点做我想要的。至少它打印的结果是正确的。但它仍然抛出几个 uncaught exception test X

    asd = async () => {
    
      // Function simulating tasks which might fail.
      function wait(ms, data) {
        return new Promise( (resolve, reject) => setTimeout(() => {
          if (Math.random() > 0.5){
            resolve(data);
          } else {
            reject(data);
          }
        }, ms) );
      }
    
      let tasks = [];
      const results = [];
    
      // start the tasks
      for ( let i = 0; i < 20; i++) {
        const prom = wait(100 * i, 'test ' + i);
        tasks.push([i, prom]);
      }
    
      // collect results and handle retries.
      for ( let tries = 0; tries < 10; tries++){
        failedTasks = [];
        for ( let i = 0; i < tasks.length; i++) {
    
          const task_idx = tasks[i][0];
    
          // Wait for the task and check whether they failed or not.
          // Any pointers on how to improve the readability of the next 6 lines appreciated.
          await tasks[i][1].then(result => {
            results.push([task_idx, result])
          }).catch(err => {
            const prom = wait(100 * task_idx, 'test ' + task_idx);
            failedTasks.push([task_idx, prom])
          });
        }
    
        // Retry the tasks which failed.
        if (failedTasks.length === 0){
          break;
        } else {
          tasks = failedTasks;
        }
        console.log('try ', tries);
      }
    
      console.log(results);
    }
    

    最后 results 数组包含(除非任务失败10次)所有结果。但仍然 uncaught exceptions 飞来飞去。

    then()/catch() 稍后会引起一些时间问题。

    任何改进或更好的解决方案,我的问题表示感谢。我的解决方案只允许“波浪式”重试。如果有人能想出一个更好的连续解决方案,我们也将不胜感激。

    1 回复  |  直到 8 年前
        1
  •  1
  •   t.niese    8 年前

    使用 await asnyc 可以更清楚地解决这个问题。

    你经过一个 tasks (执行时启动给定任务的函数)到 execute_tasks execute_task ,将任务函数传递给它 执行任务

    执行任务 作为循环,循环直到异步任务成功或达到最大重试次数。

    因为每个任务都有自己的重试循环,所以可以避免这些波动。当每个任务失败时,它将排队等待新的执行。使用 等待 这种方式创造了某种合作的多任务处理。所有的错误都会被处理,因为任务是在 try catch

    function wait(ms, data) {
      return new Promise((resolve, reject) => setTimeout(() => {
        if (Math.random() > 0.5) {
          resolve(data);
        } else {
          reject(new Error());
        }
      }, ms));
    }
    
    
    async function execute_task(task) {
      let result, lastError;
      let i = 0
      
      //loop until result was found or the retry count is larger then 10
      while (!result && i < 10) {
        try {
          result = await task()
        } catch (err) {
          lastError = err
          // maybe sleep/wait before retry
        }
        i++
      }
    
      if (result) {
        return { success: true, data: result }
      } else {
        return { success: false, err: lastError }
      }
    }
    
    async function execute_tasks(taskList) {
      var taskPromises = taskList.map(task => execute_task(task))
     
      // the result could be sorted into failed and not failed task before returning
      return await Promise.all(taskPromises)
    }
    
    
    var taskList = []
    for (let i = 0; i < 10; i++) {
      taskList.push(() => {
        return wait(500, {
          foo: i
        })
      })
    }
    
    execute_tasks(taskList)
      .then(result => {
        console.dir(result)
      })