让我们说我在Javascript中有一个诺言,我希望他们一次解析n
诺言。有什么好方法吗?
我可以有一个名为promisesInProgress
的状态数组,并且每个诺言都可以监视其长度吗?在外部,我将使用Promise.all()。但是在每个promise中,我希望它检查状态数组promisesInProgress,并且仅在该数组的长度小于n时才触发。那行得通吗?
如果我要确保这些诺言不会太快地解决并限制它们怎么办?
这有一个好的模式吗?
答案 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)
如果您希望获得每个承诺内发生的其他进度,那么只要在每个承诺内进行了计数,就增加计数器。