承诺链中承诺之间的延迟
Delays between promises in promise chain
假设我正在使用以下代码运行一系列的承诺:
let paramerterArr = ['a','b','c','d','e','f']
parameterArr.reduce(function(promise, item) {
return promise.then(function(result) {
return mySpecialFunction(item);
})
}, Promise.resolve())
代码简单地调用了 mySpecialFunction(returns 一个承诺),等待承诺得到解决,然后再次调用 mySpecialFunction 等等。所以函数为数组中的每个元素调用一次,在正确的顺序。
如何确保每次调用 mySpecialFunction(item)
之间至少有 50 毫秒的延迟?
以正确的顺序执行承诺很重要,mySpecialFunction
的执行时间每次都不同。
我想同步睡眠会起作用,但我不打算 运行 将此代码放在单独的线程中,因此它会导致令人讨厌的 ui 浏览器冻结。
我不确定 setTimer 是否可以用于此目的。我的意思是我不能延迟承诺的回报。
以下示例展示了如何实现不阻塞但等待指定时间段的承诺:
function timedPromise(ms, payload) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(payload);
}, ms);
})
}
var time = Date.now();
timedPromise(1000)
.then(function() {
console.log(time - Date.now());
return timedPromise(2000);
}).then(function() {
console.log(time - Date.now());
return timedPromise(3000);
});
因此,根据您的具体需要,您应该能够执行如下操作:
let paramerterArr = ['a','b','c','d','e','f']
parameterArr.reduce(function(promise, item) {
return promise.then(function(result) {
return mySpecialFunction(item);
}).then(function(specialResult) {
return timedPromise(50, specialResult);
});
}, Promise.resolve())
我称之为一个非常方便的实用函数 delay()
:
function delay(t, val) {
return new Promise(function(resolve) {
if (t <= 0) {
resolve(val);
} else {
setTimeout(resolve.bind(null, val), t);
}
});
}
然后,您可以像这样在承诺链中使用它:
let paramerterArr = ['a','b','c','d','e','f']
parameterArr.reduce(function(promise, item, index) {
return promise.then(function(result) {
// no delay on first iteration
var delayT = index ? 50 : 0;
return delay(delayT, item).then(mySpecialFunction);
})
}, Promise.resolve());
您还可以创建一个小的实用函数来执行带有可选延迟的顺序迭代:
// delayT is optional (defaults to 0)
function iterateSerialAsync(array, delayT, fn) {
if (!fn) {
fn = delayT;
delayT = 0;
}
array.reduce(function(p, item, index) {
return p.then(function() {
// no delay on first iteration
if (index === 0) delayT = 0;
return delay(delayT, item).then(fn)
});
}, Promise.resolve());
}
然后你会像这样使用它:
iterateSerialAsync(paramerterArr, 50, mySpecialFunction).then(function(finalVal) {
// all done here
});
给你:https://jsbin.com/suvasox/edit?html,js,console
let paramerterArr = ['a','b','c','d','e','f']
paramerterArr.reduce((p, val) => {
return p.then(() => {
return new Promise((res) => {
setTimeout(() => { res(mySpecialFunction(val)); }, 1000);
});
});
}, Promise.resolve());
p 必须是 p.then() 的结果。只有这样,您才能将承诺串起来。
注意,为了强调,我将其更改为 1000 毫秒延迟。
答案很好,但是他们等待的时间太长了,因为所有答案都在等待不管实际操作是否已经超过 50 毫秒。
你可以用Promise.all
来代替它。
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
let parameterArr = ['a','b','c','d','e','f'];
parameterArr.reduce(function(promise, item) {
return promise.then(function(result) {
return Promise.all([delay(50), myPromise(item)]);
});
}, Promise.resolve());
要延迟 至少 50 毫秒,请使用 Promise.all
:
function delay(t) {
return new Promise(function(resolve) {
setTimeout(resolve, t);
});
}
parameterArr.reduce(function(promise, item) {
return promise.then(function() {
return Promise.all([
mySpecialFunction(item),
delay(50)
]);
});
}, Promise.resolve());
因为这似乎是 mySpecialFunction
的要求,所以我会在那里实现它。因此,如果函数在上次调用后不到 50 毫秒被调用,则会延迟自身
const delayBetweenCalls = (delay, fn) => {
let lastCall = NaN;
return function(/*...arguments*/){
//this and arguments are both forwarded to fn
return new Promise(resolve => {
let poll = () => {
let delta = Date.now() - lastCall;
if(delta < delay){
setTimeout(poll, delta - delay);
}else{
lastCall = Date.now();
resolve( fn.apply(this, arguments) );
}
}
poll();
})
}
}
然后:
const mySpecialFunction = delayBetweenCalls(50, function(some, ...args){
return someValueOrPromise;
});
//and your loop stays the same:
parameterArr.reduce(function(promise, item) {
return promise.then(function(result) {
return mySpecialFunction(item);
})
}, Promise.resolve())
所以没关系 where/how mySpecialFunction
被调用,在它运行传递的回调中的代码之前总会有至少 50 毫秒的延迟。
这是我对延迟承诺序列的完整解决方案:
function timeout_sequence_promise(promises = [], timeout = 200) {
//fake promise used as buffer between promises from params
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
//we need to create array of all promises with delayed buffers
let delayed_promises = [];
let total = promises.length;
let current = 0;
//every odd promise will be buffer
while (current < total) {
delayed_promises.push(promises[current]);
delayed_promises.push(delay(timeout));
current++;
}
return Promise.all(delayed_promises).then((result) => {
//we need to filter results from empty odd promises
return result.filter((item, index) => (index+2)%2 === 0);
});
}
它接收承诺数组和它们之间以毫秒为单位的超时延迟作为参数。
希望对你有所帮助!
假设我正在使用以下代码运行一系列的承诺:
let paramerterArr = ['a','b','c','d','e','f']
parameterArr.reduce(function(promise, item) {
return promise.then(function(result) {
return mySpecialFunction(item);
})
}, Promise.resolve())
代码简单地调用了 mySpecialFunction(returns 一个承诺),等待承诺得到解决,然后再次调用 mySpecialFunction 等等。所以函数为数组中的每个元素调用一次,在正确的顺序。
如何确保每次调用 mySpecialFunction(item)
之间至少有 50 毫秒的延迟?
以正确的顺序执行承诺很重要,mySpecialFunction
的执行时间每次都不同。
我想同步睡眠会起作用,但我不打算 运行 将此代码放在单独的线程中,因此它会导致令人讨厌的 ui 浏览器冻结。
我不确定 setTimer 是否可以用于此目的。我的意思是我不能延迟承诺的回报。
以下示例展示了如何实现不阻塞但等待指定时间段的承诺:
function timedPromise(ms, payload) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(payload);
}, ms);
})
}
var time = Date.now();
timedPromise(1000)
.then(function() {
console.log(time - Date.now());
return timedPromise(2000);
}).then(function() {
console.log(time - Date.now());
return timedPromise(3000);
});
因此,根据您的具体需要,您应该能够执行如下操作:
let paramerterArr = ['a','b','c','d','e','f']
parameterArr.reduce(function(promise, item) {
return promise.then(function(result) {
return mySpecialFunction(item);
}).then(function(specialResult) {
return timedPromise(50, specialResult);
});
}, Promise.resolve())
我称之为一个非常方便的实用函数 delay()
:
function delay(t, val) {
return new Promise(function(resolve) {
if (t <= 0) {
resolve(val);
} else {
setTimeout(resolve.bind(null, val), t);
}
});
}
然后,您可以像这样在承诺链中使用它:
let paramerterArr = ['a','b','c','d','e','f']
parameterArr.reduce(function(promise, item, index) {
return promise.then(function(result) {
// no delay on first iteration
var delayT = index ? 50 : 0;
return delay(delayT, item).then(mySpecialFunction);
})
}, Promise.resolve());
您还可以创建一个小的实用函数来执行带有可选延迟的顺序迭代:
// delayT is optional (defaults to 0)
function iterateSerialAsync(array, delayT, fn) {
if (!fn) {
fn = delayT;
delayT = 0;
}
array.reduce(function(p, item, index) {
return p.then(function() {
// no delay on first iteration
if (index === 0) delayT = 0;
return delay(delayT, item).then(fn)
});
}, Promise.resolve());
}
然后你会像这样使用它:
iterateSerialAsync(paramerterArr, 50, mySpecialFunction).then(function(finalVal) {
// all done here
});
给你:https://jsbin.com/suvasox/edit?html,js,console
let paramerterArr = ['a','b','c','d','e','f']
paramerterArr.reduce((p, val) => {
return p.then(() => {
return new Promise((res) => {
setTimeout(() => { res(mySpecialFunction(val)); }, 1000);
});
});
}, Promise.resolve());
p 必须是 p.then() 的结果。只有这样,您才能将承诺串起来。
注意,为了强调,我将其更改为 1000 毫秒延迟。
答案很好,但是他们等待的时间太长了,因为所有答案都在等待不管实际操作是否已经超过 50 毫秒。
你可以用Promise.all
来代替它。
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
let parameterArr = ['a','b','c','d','e','f'];
parameterArr.reduce(function(promise, item) {
return promise.then(function(result) {
return Promise.all([delay(50), myPromise(item)]);
});
}, Promise.resolve());
要延迟 至少 50 毫秒,请使用 Promise.all
:
function delay(t) {
return new Promise(function(resolve) {
setTimeout(resolve, t);
});
}
parameterArr.reduce(function(promise, item) {
return promise.then(function() {
return Promise.all([
mySpecialFunction(item),
delay(50)
]);
});
}, Promise.resolve());
因为这似乎是 mySpecialFunction
的要求,所以我会在那里实现它。因此,如果函数在上次调用后不到 50 毫秒被调用,则会延迟自身
const delayBetweenCalls = (delay, fn) => {
let lastCall = NaN;
return function(/*...arguments*/){
//this and arguments are both forwarded to fn
return new Promise(resolve => {
let poll = () => {
let delta = Date.now() - lastCall;
if(delta < delay){
setTimeout(poll, delta - delay);
}else{
lastCall = Date.now();
resolve( fn.apply(this, arguments) );
}
}
poll();
})
}
}
然后:
const mySpecialFunction = delayBetweenCalls(50, function(some, ...args){
return someValueOrPromise;
});
//and your loop stays the same:
parameterArr.reduce(function(promise, item) {
return promise.then(function(result) {
return mySpecialFunction(item);
})
}, Promise.resolve())
所以没关系 where/how mySpecialFunction
被调用,在它运行传递的回调中的代码之前总会有至少 50 毫秒的延迟。
这是我对延迟承诺序列的完整解决方案:
function timeout_sequence_promise(promises = [], timeout = 200) {
//fake promise used as buffer between promises from params
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
//we need to create array of all promises with delayed buffers
let delayed_promises = [];
let total = promises.length;
let current = 0;
//every odd promise will be buffer
while (current < total) {
delayed_promises.push(promises[current]);
delayed_promises.push(delay(timeout));
current++;
}
return Promise.all(delayed_promises).then((result) => {
//we need to filter results from empty odd promises
return result.filter((item, index) => (index+2)%2 === 0);
});
}
它接收承诺数组和它们之间以毫秒为单位的超时延迟作为参数。
希望对你有所帮助!