形势
我有一个异步函数,它需要~X seconds
来解析。持续时间取决于网络延迟,因此不可预测。该功能由用户输入触发(想想"将当前表单值保存到服务器"(
我希望防止此函数同时运行多次。
我也想";队列";调用函数,以便在适当的时候进行潜在的调用。
问题
(A( 有没有一个术语来表示";病人";异步函数。
(B( 有没有一种工具(类似于debounce(会采用异步函数并将其转换为";病人";一
此答案基于@danh的答案。
函数queuePromise
接受一个返回promise的函数。每当调用排队函数时,它的promise都会链接到上一次调用的promise。
@danh的答案与此的主要区别在于,排队函数可以接收参数,promise是一个简单的let
变量。
const queuePromise = fn => {
let pending = Promise.resolve()
return (...args) => {
const func = () => fn(...args)
return pending = pending.then(func, func)
}
}
const demo = name => id => {
console.log(`started ${name} ${id}`)
return new Promise((resolve, reject) => {
setTimeout(() => {
// example of a failed promise in the middle of the chain
if(id === 2) reject(`failed ${name} ${id}`)
else resolve(`ended ${name} ${id}`)
}, 500)
})
}
const patientFoo = queuePromise(demo('foo'))
patientFoo(1).then(console.log).catch(console.log)
patientFoo(2).then(console.log).catch(console.log)
patientFoo(3).then(console.log).catch(console.log)
const patientBar = queuePromise(demo('bar'))
patientBar(1).then(console.log).catch(console.log)
patientBar(2).then(console.log).catch(console.log)
patientBar(3).then(console.log).catch(console.log)
下面,makePatient
将一个给定的函数封装在另一个函数中,该函数只有在解析了之前的调用链后才能调用它。
function pause() {
return new Promise(resolve => {
setTimeout(resolve, 1000)
})
}
function foo(str) {
return pause().then(() => console.log(str));
}
function bar(str) {
return pause().then(() => console.log(str));
}
function makePatient(fn) {
let pending = Promise.resolve();
return (...params) => {
return pending = pending.then(() => fn(...params)).catch(console.log);
}
}
let patientFoo = makePatient(foo);
let patientBar = makePatient(bar);
patientFoo('foo');
patientFoo('foo');
patientFoo('foo');
patientBar('bar');
patientBar('bar').finally(() => console.log("all the bars are closed"));