如何控制 Promise.all 任务(暂停所有任务、仅更新一个任务的变量、恢复所有任务)

问题描述 投票:0回答:1

我在我一直在编码的节点类中偶然发现了一个设计问题。

我需要同时执行 X 数量的任务(使用 Promise.all),但这些任务共享类上下文中的值 (this.value)。

这个值会过期,但是确定它是否过期的唯一方法是在许多异步任务之一中检查它,因此这就引发了问题:

当这个值过期时,我需要更新它,但我只能从异步任务内部调用一个方法来更新它(例如:this.refreshValue),导致一堆并发运行的任务调用该方法,而我需要值过期后仅调用一次。

基本上,第一个注意到该值已过期的任务应该停止所有其他任务,以某种方式单独更新该值,而不会受到其他任务的干扰,然后恢复自身和所有其他任务。

这是该类的概要(无用,但给出了代码的一般概念)

class MyClass {
  constructor() {
  }

  async refreshSharedValue() {...}

  async doWork() {
    Promise.all([...].map(x => {
      ... Do Stuff with    this.sharedValue
      if (this.sharedValue is expired) {
        // Stop ALL tasks inside Promise.all, call this.refreshSharedValue only ONCE, resume all tasks inside Promise.all
      }
    }))
  }
}

尝试在全局变量上使用事件发射器和一些代理逻辑,但我无法立即阻止所有任务执行刷新逻辑。 我只是想不出一种方法来避免这种情况,可能我不得不不使用 Promise.all。

node.js multithreading asynchronous concurrency promise.all
1个回答
0
投票

我想有很多方法可以实现这一目标。我会分享承诺之间的状态。您可以利用单线程 Node.js 一次更改状态的状态,其他 Promise 只会等待共享状态具有继续所需的值,这是我所做的示例:



class CustomClass{
   sharedValue;
   tasks = [];


   async refreshingStatus(){
      return new Promise((resolve) => {
        setTimeout(() => {
          console.log('Call one time')
          this.sharedValue.status = 'OK';
          resolve('OK');
        }, 3000);
      });
   }

   randomAsyncTask(){
    return () => {
        return new Promise((resolve) => {
            setTimeout(async () => {
                while(this.sharedValue.status !== 'OK'){
                  if(this.sharedValue.status !== 'REFRESHING'){
                    console.log('Refreshing status');
                    this.sharedValue.status = 'REFRESHING';
                    this.sharedValue.status = await this.refreshingStatus();
                  }
                  await new Promise(r => setTimeout(r, 2000));
                }
                console.log('Task completed')
                resolve('OK');
            }, 1000);
        });
    }
}

   constructor(){
      this.sharedValue = {
        status: 'NO-OK',
      }
      // Populate 10 tasks to the array
      for(let i = 0; i < 10; i++){
        this.tasks.push(this.randomAsyncTask());
      }
   }

    async run(){
      Promise.all(this.tasks.map(task => task())).then((results) => {
        console.log('All tasks were completed');
      });
    }
}

const customClass = new CustomClass();
customClass.run();
© www.soinside.com 2019 - 2024. All rights reserved.