我是Node的新手,但我知道编写同步函数是件坏事。我锁定了事件循环或其他东西......所以把所有东西写成异步都很好。
但在某些情况下,编写所有异步可能都很糟糕。例如,我有一个函数进行API调用(到第三方API服务),然后我必须将结果写入数据库。我需要在很短的时间内完成这一工作,例如500次。
调用此API 500次异步,然后写入数据库500次async可能会禁止我从API服务(限制)和重载我的数据库服务器。
控制或限制此类内容的最佳方法是什么?我想让事情保持同步,所以它很有效,但我根本无法采取上述方法。
我研究了一些Promise throttling方法。这是解决此类问题的正确方法吗?有更好的方法吗?
答案 0 :(得分:1)
我不确定Promise throttle是如何工作的,我相信Promise
是一种比setTimeout
更好的方法,并承诺它更基于事件,我的问题是npm包是的,一旦你的电话完成,它就不提供回叫选项,我的实现将是:
class PromiseThrottler {
constructor(maxParallelCalls) {
this.maxParallelCalls = maxParallelCalls;
this.currentCalls = 0; // flag holding the no. of parallel calls at any point
this.queue = []; // queue maintaining the waiting calls
}
// pormiseFn - the fn that wraps some promise call the we need to make, thenChain - callback once your async call is done, args- arguments that needs to be passed to the function
add(promiseFn, thenChain, ...args) {
this.queue.push({
promiseFn, thenChain, args
});
this.call();
}
call() {
if (!this.queue.length || this.currentCalls >= this.maxParallelCalls) return;
this.currentCalls++;
let obj = this.queue.shift();
let chain = obj.args.length ? obj.promiseFn(...obj.args) : obj.promiseFn();
if (obj.thenChain) chain.then(obj.thenChain);
chain
.catch(() => {})
.then(() => {
this.currentCalls--;
this.call();
});
this.call();
}
}
//usage
let PT = new PromiseThrottler(50)
, rn = max => Math.floor(Math.random() * max) // generate Random number
, randomPromise = id => new Promise(resolve => setTimeout(() => resolve(id), rn(5000))) // random promise generating function
, i = 1
, thenCall = id => {
console.log('resolved for id:', id);
let div = document.createElement('div');
div.textContent = `resolved for id: ${id}`;
document.body.appendChild(div);
};
while (++i < 501) PT.add(randomPromise, thenCall, i);
&#13;
答案 1 :(得分:1)
async
npm包很棒,有几种解决方案可以在这种特殊情况下使用。一种方法是使用具有设置并发限制的queue
(直接从async
README获取的示例):
// create a queue object with concurrency 2
var q = async.queue(function (task, callback) {
console.log('hello ' + task.name);
callback();
}, 2);
// assign a callback
q.drain = function() {
console.log('all items have been processed');
}
// add some items to the queue
q.push({name: 'foo'}, function (err) {
console.log('finished processing foo');
});
在您的特定情况下,只需等待callback()
,直到您等待的时间或交易细节完成为止。
答案 2 :(得分:-1)
限制此操作的一种简单方法是使用setTimeout
并执行这样的“递归”循环。
function asyncLoop() {
makeAPICall(function(result) {
writeToDataBase(result, function() {
setTimeout(asyncLoop, 1000);
});
});
}
当然,你也可以在承诺中使用相同的策略。