Обещания Javascript: мониторинг состояния массива - PullRequest
1 голос
/ 24 марта 2019

Допустим, у меня есть массив обещаний в Javascript, и я хочу, чтобы они разрешали n обещаний одновременно. Какой хороший способ сделать это?

Могу ли я иметь массив состояний с именем promisesInProgress, чтобы каждое обещание отслеживало его длину? Снаружи я буду использовать Promise.all (). Но в каждом обещании я хочу, чтобы он проверял массив состояний, promisesInProgress, и запускался только тогда, когда длина этого массива

Что, если я хочу убедиться, что эти обещания не выполняются слишком быстро, задушить их?

Есть хороший шаблон для этого?

Ответы [ 4 ]

1 голос
/ 24 марта 2019

Обещания «выполняются», как только они появляются, поэтому, когда у вас есть их массив, вы не можете ожидать, что некоторые из них будут задержаны.

Однако вы могли бы работать смассив функций , которые - при вызове - вернут новое обещание.Параметр max будет определять, сколько из этих функций вы на самом деле будете вызывать немедленно, а остальные функции будут вызываться только тогда, когда «комната» станет доступной после разрешения одного из обещаний.

Вот как вы могли бы это сделатьсделать это:

// Main function. 
// Parameters:
// - the maximum number of unresolved promises that may exist at a given time
// - an array of promise-creating functions 
function throttle(maxPending, asyncFuncs) {
    return new Promise((resolve, reject) => {
        let numPending = 0;
        let nextFuncId = 0;
        const promisedValues = [];
        (function check() {
            if (nextFuncId >= asyncFuncs.length) { // All promises created
                if (numPending == 0) resolve(promisedValues); // All promises fulfilled
                return;
            }
            while (numPending < maxPending) { // Room for creating promise(s)
                numPending++;
                const thisFuncId = nextFuncId++;
                asyncFuncs[thisFuncId]().then(value => {
                    promisedValues[thisFuncId] = value;
                    numPending--;
                    check();
                }).catch(reject);
            }
        })();
    });
}

// Demo: 
// The usual delay function: returns a promise that resolves after given delay
const delay = (ms) => {
    console.log("Start delay of " + ms + "ms");
    return new Promise(resolve => setTimeout(resolve, ms))
            .then(() => console.log("End delay of " + ms + "ms"));
};

// Curry for the above: pass the milliseconds and return a function 
//   that can create a promise for it
const delayF = (ms) => delay.bind(null, ms);

// Pass 5 promise-creating functions, but only allow 3 concurrently pending promises:
throttle(3, [delayF(1000), delayF(500), delayF(800), delayF(300), delayF(900)])
    .then(() => console.log("all done"));  
1 голос
/ 24 марта 2019

Я хочу, чтобы они разрешали n обещаний одновременно. Какой хороший способ сделать это?

Использование Promise.all :

const prom1 = Promise.resolve(1);
const prom2 = Promise.resolve(2);

Promise.all([prom1, prom2]).then(console.log);

Могу ли я иметь массив с именем promisesInProgress, и каждое обещание должно отслеживать его длину?

Да, но это не встроенный код, но вы можете написать что-то похожее:

const promises = [
  new Promise(resolve => setTimeout(() => resolve(1), 1000)),
  new Promise(resolve => setTimeout(() => resolve(2), 2000)),
];
const resolved = promises.map(() => null);

promises.forEach((promise, index) => {
  promise.then(data => {
    resolved[index] = data;
    const nbResolved = resolved.filter(x => x!==null).length;
    console.log({resolved, nbResolved});
  })
});

Что, если я хочу, чтобы эти обещания не выполнялись слишком быстро, задушив их?

Вы можете отложить их создание . Как только обещание создано, вы не можете его замедлить.

Есть ли хороший шаблон для этого?

На самом деле никаких обещаний нет. Они настолько минимальны, насколько это возможно, позволяя вам выбрать, как их кодировать. Я бы порекомендовал async/await, чтобы сделать ваш код более плоским.


Если вы хотите иметь много встроенных модулей для асинхронного кода, Promises не будет иметь никаких шансов. RxJS , сложная, но очень мощная библиотека для обработки асинхронного кода. Он имеет встроенные модули для дросселирования, трубопроводов, многоадресной рассылки и многого другого!

0 голосов
/ 24 марта 2019

Во-первых, регулирование не является решением проблемы. Вы никогда не хотите остановить пользовательский опыт. Без некоторого кода трудно определить, что именно вы пытаетесь сделать здесь, поэтому пример был бы хорош.

Существует множество различных способов отслеживания прогресса связки обещаний. Но они в основном зависят от того, что вы хотите отслеживать. Вы хотите отслеживать, когда каждое отдельное обещание выполнено? Просто обратитесь к функции, которая увеличивает счетчик. Чтобы получить Процент Прогресса просто сделайте некоторую основную математику как ниже:

let promise_array = [...] // Your array of Promise objects
let counter = 0;
let total = promise_array.length

Promise.all(promise_array)

// inside each promise
counter++;

// to get progress
let progress = Math.round(counter/total*100,2)

Если вы хотите получить какой-то другой уровень прогресса, который происходит внутри каждого обещания, то увеличивайте счетчик всякий раз, когда это происходит внутри каждого обещания.

0 голосов
/ 24 марта 2019

Я думаю, что Promise.all () может работать для вас: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Пример:

Promise.all([
getData('https://my-json-server.typicode.com/typicode/demo/db'),
getData('https://my-json-server.typicode.com/typicode/demo/db')
]).then(
json => console.log(json), // JSON obj
).catch(
err => console.log(err.message) // // ERROR ERROR //
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...