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

时间:2017-04-06 18:06:49

标签: javascript ecmascript-6 promise es6-promise

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

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

我需要:

  • 保持承诺解决顺序,并考虑事先不知道完整的行动清单。

我可以使用ES6和浏览器本机Promise

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

  (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>

2 个答案:

答案 0 :(得分:1)

您可以将新的操作函数附加到单个promise中,以确保在所有先前的操作都已解决之后才会评估操作:

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>

答案 1 :(得分:0)

您不应该创建自己的解决方案。相反,请从https://www.npmjs.com/search?q=promise+queue

中选择大约158个现有解决方案中的一个