Я хочу гарантировать минимальную задержку выполнения обещания bluebird.js.
В качестве примера предположим, что я делаю запрос, заключенный в обещание. Поведение, которое я хочу, заключается в том, что если запрос занимает менее 5 секунд, я хочу искусственно увеличить задержку разрешения обещания до 5 секунд. Если бы запрос занимал более 5 секунд, я бы не хотел добавлять искусственную задержку, так что это немного сложнее, чем просто добавлять статическую задержку к каждому запросу. Все это должно быть полностью скрыто от потребителя промиса — он должен просто видеть, что промис решается за 5 секунд или больше.
Чтобы продемонстрировать, у меня есть простой пример фиктивной реализации, в котором задержка фиктивного запроса жестко задана в 3 секунды.
Моя первая попытка прошла примерно так: использование setTimeout для обеспечения того, чтобы обратный вызов разрешения не вызывался до истечения 5 секунд.
function getTimestamp() {
return new Date().getTime();
}
function makeCallWith3SecondLatency(cb) {
console.log('mocking a call with 3 second latency...');
var mockResult = 'the result';
setTimeout(function() { cb(mockResult); }, 3000);
}
function doSomethingAsync(minDelay) {
return new Promise(function(resolve) {
var calledAt = getTimestamp();
makeCallWith3SecondLatency(function(arg) {
var actualDelay = getTimestamp() - calledAt;
if(actualDelay < minDelay) {
var artificialDelay = minDelay - actualDelay;
console.log('artificially delay another ' + artificialDelay + ' millis');
setTimeout(function() { resolve(arg); }, artificialDelay);
} else {
resolve(arg);
}
});
});
}
function printResult(result) {
console.log('result: ' + result)
}
var minDelay = 5000;
doSomethingAsync(minDelay).then(printResult);
Много шаблонов.
Затем с помощью этого ответа я обнаружил, что могу использовать функцию Promise.join для присоединения к упаковке обещания запрос с Promise.delay с минимальной 5-секундной задержкой для достижения того же результата:
function makeCallWith3SecondLatency(cb) {
console.log('mocking a call with 3 second latency...');
var mockResult = 'the result';
setTimeout(function() { cb(mockResult); }, 3000);
}
function doSomethingAsync(minDelay) {
return Promise.join(
new Promise(function(resolve) { makeCallWith3SecondLatency(resolve); }),
Promise.delay(minDelay).then(function() { console.log('artificially delaying 5 seconds with Promise.delay') }),
function(result) { return result; });
}
function printResult(result) {
console.log('result: ' + result)
}
var minDelay = 5000;
doSomethingAsync(minDelay).then(printResult);
Это чище, но все же немного более шаблонно, чем хотелось бы - я копался в ссылка на API bluebird и не может найти функцию, которая делает это напрямую.
У меня простой вопрос: может ли кто-нибудь предложить более чистый, более декларативный способ достижения такого поведения с bluebird, чем во втором примере?
Любые предложения других библиотек обещаний, где API предлагает это, также будут оценены.