gpt4 book ai didi

javascript - Node.js:防止多个同时调用异步函数

转载 作者:太空宇宙 更新时间:2023-11-04 01:50:01 24 4
gpt4 key购买 nike

在单线程、同步、非递归代码中,我们可以确定对于任何给定的函数,一次不会有超过一次的调用。

但是,在 async/await 世界中,上述内容不再适用:当我们在执行异步函数 f 期间等待某些内容时,它可能会再次被调用。

我突然想到,使用事件发射器和队列,我们​​可以为异步函数编写一个包装器,以保证它一次不会有多个调用。像这样的事情:

const events = require('events')

function locked(async_fn) {
const queue = [] // either actively running or waiting to run
const omega = new events()

omega.on('foo', () => {
if (queue.length > 0) {
queue[0].emit('bar')
}
})

return function(...args) {
return new Promise((resolve) => {
const alpha = new events()
queue.push(alpha)
alpha.on('bar', async () => {
resolve(await async_fn(...args))
queue.shift()
omega.emit('foo')
})
if (queue.length === 1) omega.emit('foo')
})
}
}

这个想法是,如果 f 是一个异步函数,那么 locked(f) 就是一个执行相同操作的函数,只不过如果在 f 执行期间调用 f,则新的调用在第一个调用返回之前不会开始。

我怀疑我的解决方案还有很大的改进空间,所以我想知道:是否有更好的方法来做到这一点?事实上,Node 中是否已经内置了一个,或者可以通过 npm 获得?

<小时/>

编辑以显示如何使用它:

async function f() {
console.log('f starts')
await new Promise(resolve => setTimeout(resolve, 1000))
console.log('f ends')
}

const g = locked(f)

for (let i = 0; i < 3; i++) {
g()
}

运行该命令需要 3 秒,我们得到以下输出:

f starts
f ends
f starts
f ends
f starts
f ends

如果我们在 for 循环中将 g() 替换为 f(),则执行需要 1 秒并得到以下结果:

f starts
f starts
f starts
f ends
f ends
f ends
<小时/>

(我意识到这是一个相当小的问题,如果它不适合 stackoverflow,我表示歉意,但我不知道有更好的地方。)

最佳答案

如果您偶然发现这个问题,这里的代码完全符合OP的要求:

const disallowConcurrency = (fn) => {
let inprogressPromise = Promise.resolve()

return (...args) => {
inprogressPromise = inprogressPromise.then(() => fn(...args))

return inprogressPromise
}
}

像这样使用它:

const someAsyncFunction = async (arg) => {
await new Promise( res => setTimeout(res, 1000))
console.log(arg)
}

const syncAsyncFunction = disallowConcurrency(someAsyncFunction)

syncAsyncFunction('I am called 1 second later')
syncAsyncFunction('I am called 2 seconds later')

您可能还想将函数名称更改为更清晰的名称,因为 Promise 实际上与并发性无关。

关于javascript - Node.js:防止多个同时调用异步函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50067682/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com