js 一个promise数组且该数组会随时添加新promise要怎么样一个一个同步执行?

js 一个promise数组且该数组会随时添加新promise,要怎么样一个一个同步执行
有可能执行完一个promise过一会才会添加新的

阅读 1.2k
avatarAI BotBETA

对不起,这个问题存在误解。JavaScript中的Promise对象是用于处理异步操作,它们不是按照顺序一个接一个地执行的。相反,Promise是并行执行的,这意味着一旦你创建了多个Promise,它们将同时开始执行。

如果你希望Promise按照特定的顺序执行,你需要使用.then()函数或者async/await语法来确保前一个Promise在后一个Promise开始之前完成。但是,请注意,这不会阻止并行执行,只会确保在每个Promise完成后按顺序执行下一个Promise。

这里是一个基本的例子:

let promise1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 'promise1 completed');
});
let promise2 = new Promise((resolve, reject) => {
    setTimeout(resolve, 2000, 'promise2 completed');
});
let promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 3000, 'promise3 completed');
});

promise1.then(result1 => {
    console.log(result1); // 'promise1 completed'
    return promise2;
}).then(result2 => {
    console.log(result2); // 'promise2 completed'
    return promise3;
}).then(result3 => {
    console.log(result3); // 'promise3 completed'
});

在这个例子中,尽管promise1promise2promise3几乎同时开始,但promise1会首先完成,然后是promise2,最后是promise3。这就是通过.then()函数实现的Promise的顺序执行。

然而,如果你想在添加新的Promise时保持顺序,你可能需要一种不同的设计模式。你可能需要创建一个队列,每当一个新Promise完成时,就将新的Promise添加到队列的末尾。然后,你可以遍历这个队列并依次执行每个Promise。这种方法比较复杂,可能需要你自己去实现。

4 个回答

原生不支持,自己控制 promise 就行了。

先写期待的用法:

// 主进程
const myPromiseAll = new MyPromiseAll([...启动时的异步操作]);
await myPromiseAll.promise;
// 继续其它操作

// 事件函数
function onClick() {
  myPromiseAll.add(新异步操作);
}

然后简单实现一下 MyPromiseAll 这个类:

class myPromiseAll(
  promise;

  #tasks = 0;
  #count = 0;
  #resolve;
  #reject;

  constructor(tasks) {
    for (const task of tasks) {
      this.add(task);
    }
    this.promise = new Promise((resolve, reject) => {
      this.#resolve = resolve;
        this.#reject = reject;
    });
  }
  add(task) {
    task.then(() => {
      this.#count++;
      if (this.#count >= this.#tasks) {
        this.#resolve();
      }
    }).catch(err => {
      // this.#reject();
    });
    this.#tasks++;
  }
}

没测,你自己根据需求改改吧。

粗略的设计,弄个定时器,定义个全局promise数组,然后再弄个循环定时器 setInterval 不断读取这个全局数组进行执行,理论上是没问题,但是细节需要打磨

来个骚操作,用异步迭代器做promise队列(建议看懂了再用,目前没法在每次next时拿到任务执行的promise,等function.sent提案)

const sleep = async (time) => {
  console.log('start task', time, Date.now());
  return new Promise((resolve) =>
    setTimeout(() => {
      console.log('resolve', time, Date.now());
      resolve(true);
    }, time),
  );
};

async function* promiseQueue() {
  while (1) await (yield)();
}
const pmsQueue = promiseQueue();
pmsQueue.next(() => Promise.resolve(true)); // 第一次会被忽略,等function.sent提案

console.log('start:', Date.now());
pmsQueue.next(() => sleep(3000));
pmsQueue.next(() => sleep(5000));
pmsQueue.next(() => sleep(8000));
/*
start: 1699617365646
start task 3000 1699617365646
resolve 3000 1699617368656
start task 5000 1699617368657
resolve 5000 1699617373666
start task 8000 1699617373667
resolve 8000 1699617381675
*/
新手上路,请多包涵

要一个一个同步执行,用一个叫p-limit的工具最方便

import pLimit from 'p-limit'

// 一个一个执行,那就限制1个并发
const limit = pLimit(1)

limit(() => fetchSomething('foo'))
limit(() => fetchSomething('bar'))
limit(() => doSomething())

// 可能在几秒之后
limit(() => doSomethingSecondsLater())
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题