Javascript许诺:监视数组的状态

时间:2019-03-24 13:45:44

标签: javascript promise

让我们说我在Javascript中有一个诺言,我希望他们一次解析n诺言。有什么好方法吗?

我可以有一个名为promisesInProgress的状态数组,并且每个诺言都可以监视其长度吗?在外部,我将使用Promise.all()。但是在每个promise中,我希望它检查状态数组promisesInProgress,并且仅在该数组的长度小于n时才触发。那行得通吗?

如果我要确保这些诺言不会太快地解决并限制它们怎么办?

这有一个好的模式吗?

4 个答案:

答案 0 :(得分:1)

  

我希望他们一次解决n个诺言。有什么好方法吗?

使用Promise.all

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

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

  

我可以有一个名为promisesInProgress的数组,并且可以让每个promise监视其长度吗?

是的,但是它不是内置的,但是您可以编写类似以下内容的代码:

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,这是一个用于处理异步代码的复杂但非常强大的库。它内置了节流,管道传输,多播等功能!

答案 1 :(得分:1)

它们一旦存在就承诺“运行”,因此,当您拥有一系列时,就不能期望延迟其中一些。

但是,您可以做的是使用一组功能,它们在被调用时会返回一个新的Promise。 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"));  

答案 2 :(得分:0)

我认为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 //
);

答案 3 :(得分:0)

首先,节流永远不是解决方案。您永远都不想拖延用户体验。没有一些代码,很难确定您到底要在这里做什么,因此举个例子很不错。

跟踪许诺的进度有多种方法。但是它们主要取决于您要跟踪的内容。您是否要跟踪每项承诺的完成时间?只需提及增加计数器的功能即可。要获得进度百分比,只需执行以下基本数学运算即可:

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)

如果您希望获得每个承诺内发生的其他进度,那么只要在每个承诺内进行了计数,就增加计数器。