防止同时调用同一Promise/async函数



形势

我有一个异步函数,它需要~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"));

最新更新