需要在 promise 解决后每 2 秒向 API 发送请求,在有限循环中运行
Need to send request to API every 2 seconds after promise is resolved, runs in finite loop
我会尽力解释我的问题。
我有 javascript Promise,2 API 和 setTimeout 正在运行。
$.each(result[1], function(i, coin) {
var coincalcClass = new coincalculationClass();
// this method returns a promise.
var highforMonth = coincalcClass.getHighLowForSpecificDays(coin.mktName, 3);
setTimeout(function() {
highforMonth.then(function (value) {
var market_name = coin.mktName;
var bestPrice = value['1'];
addAlert('BTRX', market_name, bestPrice);
}
)
}, 1000);//time in milliseconds
});
所以,在代码中,首先我有一个 json 值,(50 个值),我将遍历每个值。
我在做一些计算。
我调用 returns 承诺的 getHighLowForSpecificDays() 方法。当承诺得到解决时,我得到值并调用 addAlert() 函数,这是一个 API POST 请求。
这里的问题是代码有效,但 API 的速率限制为每秒 1 个请求。我尝试使用 setTimeout,但它不起作用,因为在我看来,承诺很快得到解决,然后绕过 setTimeout() 触发函数。
我在这里需要帮助,这样即使一秒钟内解决了所有 50 个承诺,也应该每秒调用一次 addAlert() 方法。我尝试在 .then 中的 $.each 迭代中使用 setTimeout;没有任何帮助。
任何帮助都适用!
谢谢
将对您的 API 的调用放入每 1 秒触发一次的队列中:
// Variables holding the timeout id (for cancelling) and queue to process
var queueId;
var q = [];
// This is the "run" function.
function runQueue() {
// If the queue has any items on it, then let's process one
if (q.length > 0) {
// Pull the first item off the queue (Last in, first out)
var f = q.shift();
// Run it as a function (could probably benefit from a 'typeof' check)
if (typeof f === "function") {
f();
}
}
// Set this very function to run again in 1s.
queueId = setTimeout(runQueue, 1000);
}
// Stop the queue processing
function stopQueue() {
clearTimeout(queueId);
}
// Start the queue .. the actual queue may be empty, but that won't
// bother the process as it will simply set itself up to run again
// in a second
runQueue();
$.each(result[1], function(i, coin) {
var coincalcClass = new coincalculationClass();
// this method returns a promise.
var highforMonth = coincalcClass.getHighLowForSpecificDays(coin.mktName, 3);
highforMonth.then(function(value) {
var market_name = coin.mktName;
var bestPrice = value['1'];
q.push(function() {
addAlert('BTRX', market_name, bestPrice);
});
);
});
编辑:这确实是一个快速而肮脏的队列实现。我个人最喜欢的是 p-queue,它实现了速率限制和其他漂亮的功能。
您似乎需要的是能够以 最小 1 秒间隔计量对 API 的请求,换句话说:
- 如果 API 在 1 秒内响应,那么下一个请求应该在上一个请求之后延迟到 1 秒。
- 如果 API 响应时间超过 1 秒,则可能会立即发出下一个请求。
这是一个通用的异步递归函数,它就是这样做的:
function recurseAsync(arr, fn, initialValue, minimumInterval) {
var index = 0;
var arr_ = arr.map(function(x) { return x }); // clone array (safety measure)
function delay(t) {
return $.Deferred(function(dfrd) {
setTimeout(dfrd.resolve, t);
});
}
function recurse(previous) {
return (index < arr_.length) ?
$.when(fn(previous, arr_[index++]), delay(minimumInterval)).then(recurse) :
previous;
}
return recurse(initialValue);
}
规则的实施非常简单。表达式 $.when(fn(previous, arr_[index++]), delay(minimumInterval)).then(recurse)
确保仅当 fn()
调用已解决且最小延迟已发生时才调用 recurse
。这是一种奇怪的比赛,最后一个回家的人为下一场比赛打发令枪。
coincalcClass 的用法API:
function getCoinData(previous, current) {
var coin = current;
var coincalcClass = new coincalculationClass();
return coincalcClass.getHighLowForSpecificDays(coin.mktName, 3)
.then(function(value) {
var market_name = coin.mktName;
var bestPrice = value['1'];
addAlert('BTRX', market_name, bestPrice);
return null; // appears as `previous` at next call
});
}
recurseAsync(result[1], getCoinData, null, 1000);
备注:
recurseAsync()
在概念上与 Array#reduce()
类似,但它是作为函数而不是方法编写的,并且接受 minimumInterval
参数(默认为 0)。
previous
未在此示例中使用,并使用 null
. 初始化
我会尽力解释我的问题。
我有 javascript Promise,2 API 和 setTimeout 正在运行。
$.each(result[1], function(i, coin) {
var coincalcClass = new coincalculationClass();
// this method returns a promise.
var highforMonth = coincalcClass.getHighLowForSpecificDays(coin.mktName, 3);
setTimeout(function() {
highforMonth.then(function (value) {
var market_name = coin.mktName;
var bestPrice = value['1'];
addAlert('BTRX', market_name, bestPrice);
}
)
}, 1000);//time in milliseconds
});
所以,在代码中,首先我有一个 json 值,(50 个值),我将遍历每个值。 我在做一些计算。 我调用 returns 承诺的 getHighLowForSpecificDays() 方法。当承诺得到解决时,我得到值并调用 addAlert() 函数,这是一个 API POST 请求。
这里的问题是代码有效,但 API 的速率限制为每秒 1 个请求。我尝试使用 setTimeout,但它不起作用,因为在我看来,承诺很快得到解决,然后绕过 setTimeout() 触发函数。
我在这里需要帮助,这样即使一秒钟内解决了所有 50 个承诺,也应该每秒调用一次 addAlert() 方法。我尝试在 .then 中的 $.each 迭代中使用 setTimeout;没有任何帮助。
任何帮助都适用! 谢谢
将对您的 API 的调用放入每 1 秒触发一次的队列中:
// Variables holding the timeout id (for cancelling) and queue to process
var queueId;
var q = [];
// This is the "run" function.
function runQueue() {
// If the queue has any items on it, then let's process one
if (q.length > 0) {
// Pull the first item off the queue (Last in, first out)
var f = q.shift();
// Run it as a function (could probably benefit from a 'typeof' check)
if (typeof f === "function") {
f();
}
}
// Set this very function to run again in 1s.
queueId = setTimeout(runQueue, 1000);
}
// Stop the queue processing
function stopQueue() {
clearTimeout(queueId);
}
// Start the queue .. the actual queue may be empty, but that won't
// bother the process as it will simply set itself up to run again
// in a second
runQueue();
$.each(result[1], function(i, coin) {
var coincalcClass = new coincalculationClass();
// this method returns a promise.
var highforMonth = coincalcClass.getHighLowForSpecificDays(coin.mktName, 3);
highforMonth.then(function(value) {
var market_name = coin.mktName;
var bestPrice = value['1'];
q.push(function() {
addAlert('BTRX', market_name, bestPrice);
});
);
});
编辑:这确实是一个快速而肮脏的队列实现。我个人最喜欢的是 p-queue,它实现了速率限制和其他漂亮的功能。
您似乎需要的是能够以 最小 1 秒间隔计量对 API 的请求,换句话说:
- 如果 API 在 1 秒内响应,那么下一个请求应该在上一个请求之后延迟到 1 秒。
- 如果 API 响应时间超过 1 秒,则可能会立即发出下一个请求。
这是一个通用的异步递归函数,它就是这样做的:
function recurseAsync(arr, fn, initialValue, minimumInterval) {
var index = 0;
var arr_ = arr.map(function(x) { return x }); // clone array (safety measure)
function delay(t) {
return $.Deferred(function(dfrd) {
setTimeout(dfrd.resolve, t);
});
}
function recurse(previous) {
return (index < arr_.length) ?
$.when(fn(previous, arr_[index++]), delay(minimumInterval)).then(recurse) :
previous;
}
return recurse(initialValue);
}
规则的实施非常简单。表达式 $.when(fn(previous, arr_[index++]), delay(minimumInterval)).then(recurse)
确保仅当 fn()
调用已解决且最小延迟已发生时才调用 recurse
。这是一种奇怪的比赛,最后一个回家的人为下一场比赛打发令枪。
coincalcClass 的用法API:
function getCoinData(previous, current) {
var coin = current;
var coincalcClass = new coincalculationClass();
return coincalcClass.getHighLowForSpecificDays(coin.mktName, 3)
.then(function(value) {
var market_name = coin.mktName;
var bestPrice = value['1'];
addAlert('BTRX', market_name, bestPrice);
return null; // appears as `previous` at next call
});
}
recurseAsync(result[1], getCoinData, null, 1000);
备注:
recurseAsync()
在概念上与Array#reduce()
类似,但它是作为函数而不是方法编写的,并且接受minimumInterval
参数(默认为 0)。previous
未在此示例中使用,并使用null
. 初始化