如何使用 promise 对一系列动态生成的异步操作进行排序



在下面的示例中,我模拟了一个用户可以触发某些操作的场景,每个操作都是一个异步操作(包装在 promise 中(,可以通过随机计时解决。

操作

列表也是动态的,用户在一段时间内只能触发一个或多个操作。

我需要:

  • 保持承诺决议的顺序,同时考虑到事先不知道完整的操作列表。

我可以使用 ES6 和浏览器原生承诺

若要测试该示例,请单击多次(可变频率(按钮。

  (function (window) {
            document.addEventListener('DOMContentLoaded', e => {
                let logActionsElm = document.getElementById('logActions');
                let logOperationsElm = document.getElementById('logOperations');
                let logCounterElm = document.getElementById('logCounter');
                let btnActionElm = document.getElementById('btnAction');
                let actionCounter = 0;
                let operationDurations = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000];
                let getRandomNumber = (min, max) => Math.floor(Math.random() * (max - 0 + min)) + min;
                let getRandomOperationDuration = x => operationDurations[getRandomNumber(0, 8)];
                let promises = [];
                let createAction = (id, duration) => {
                    logActionsElm.innerHTML += `${id} action_start_duration: ${duration} --------- ${id}<br>`;
                    let promiseAction = new Promise((resolve, reject) => {
                        setTimeout(e => {
                            logActionsElm.innerHTML += `${id} action_end___duration: ${duration} --------- ${id}<br>`;
                        }, duration);
                    });
                };
                let createOperation = x => {
                    actionCounter++;
                    let duration = getRandomOperationDuration() / 10;
                    createAction(actionCounter, duration);
                    //logActionsElm.innerHTML += `action ${actionCounter} created will resolve after ${duration}<br>`;
                };
                btnActionElm.addEventListener('click', e => {
                    createOperation();
                });
                var counter = 0;
                setInterval(x => {
                    if (counter >= 20) {
                        return;
                    }
                    counter++;
                    logCounterElm.innerHTML += `${counter} second <br>`;
                }, 1000);
            });
        })(window);
        body {
            font-size: 1.5em;
            font-family: 'Courier New';
        }
        #logCounter {
            position: fixed;
            top: 0;
            right: 0;
            margin: 2em;
        }
    <button id="btnAction">Triger and action</button>
    <div id="logActions"></div>
    <div id="logOperations"></div>
    <div id="logCounter"></div>

您可以将新的操作函数附加到单个承诺,以确保在解决所有先前的操作之前不会评估操作:

let queue = Promise.resolve();
let userActionIdCounter = 0;
function queueAction(fn) {
  queue = queue.then(fn);
  return queue;
}
function userAction() {
  return new Promise((resolve) => {
    const seconds = Math.ceil(Math.random() * 5);
    const actionId = userActionIdCounter;
    userActionIdCounter += 1;
    console.log('User action', userActionIdCounter, 'started');
    setTimeout(() => {
      console.log('User action', userActionIdCounter, 'complete');
      resolve();
    }, seconds * 1000);
  });
}
document.getElementById('action').addEventListener('click', () => {
  queueAction(userAction);
});
<button id='action'>Trigger action</button>

您不应该创建自己的解决方案。 相反,请从此处的大约 158 个现有解决方案中选择一种 https://www.npmjs.com/search?q=promise+queue

最新更新