簡體   English   中英

JavaScript 創建沒有異步/等待的 promise 隊列

[英]JavaScript create promise queue without async/await

我正在嘗試創建一個所謂的“承諾隊列”。 這個想法是,只要還有要解決的承諾,我們就可以繼續向隊列中添加更多承諾。

我正在挑戰自己在不使用async/await語法的情況下實現這個 promise 隊列,因為我想看看是否有可能在沒有這種語法的情況下有效地做到這一點。

我嘗試的方法是使用Promise.all但傳遞一個自定義的可迭代 object,如果它們准時到來,它將不斷產生新的承諾。 問題是, Promise.all不會懶惰地迭代可迭代對象,而是在一開始就一次性迭代所有承諾。

關於如何在沒有異步/等待語法的情況下有效地實現 promise 隊列的任何其他想法?

let createPromise = () => {
    let resolve, reject;
    let promise = new Promise((resolve_, reject_) => {
        resolve = resolve_;
        reject = reject_;
    });

    return [promise, resolve, reject];
}

let timeout = (ms) => {
    let [promise, resolve, _reject] = createPromise();
    setTimeout(resolve, ms);
    return promise;
};

class PromiseQueue {
    constructor() {
        this._queue = new Set();
    }

    add(promise) {
        this._queue.add(promise);
    }

    all() {
        let self = this;
        let alreadyIterated = false;

        return Promise.all({
            [Symbol.iterator]: function*() {
                if (alreadyIterated) {
                    console.error("already iterated");
                    throw new Error("already iterated");
                }

                alreadyIterated = true;

                while (true) {
                    let { value: promise, done } = self._queue.values().next();
                    
                    if (done) {
                        return;
                    }
                    
                    self._queue.delete(promise);
                    console.log("deleting");

                    yield promise;
                }
            }
        });
    }
}

let queue = new PromiseQueue();
queue.add(timeout(1000));

setTimeout(() => {
    queue.add(timeout(1000));   
    queue.add(timeout(1000));
}, 500);

let result = await queue.all();
console.log(result);

你可以這樣做:


all() {
  var iterator = this._queue.values();
  function iterate() {
    let v = iterator.next();
    if (!v.done) {
      return v.value.then(iterate);
    }
  }
  return Promise.resolve(iterate());
}

這是受其他答案啟發的更新的PromiseQueue實現。

class PromiseQueue {
    constructor() {
        this._queue = [];
    }

    add(promise) {
        this._queue.push(promise);
    }

    all() {
        return this._all([]);
    }

    _all(results) {
        let all = Promise.all(this._queue);
        this._queue = [];

        return all.then((newResults) => {
            results.push(...newResults);

            if (this._queue.length > 0) {
                return this._all(results);
            }

            return results;
        });
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM