Javascript 多个调用者可以使用Babel Wait关键字订阅同一个异步函数吗?
如果函数返回CommonJS承诺,则多个调用方可以订阅正在进行的函数:Javascript 多个调用者可以使用Babel Wait关键字订阅同一个异步函数吗?,javascript,async-await,babeljs,es6-promise,Javascript,Async Await,Babeljs,Es6 Promise,如果函数返回CommonJS承诺,则多个调用方可以订阅正在进行的函数: let curWaitTask; let lastWaitTime = new Date(1970, 0, 1); let func1 = function() { if(curWaitTask) { return curWaitTask; } if((new Date() - lastWaitTime) > TWENTY_MINUTES) { lastWaitTime = new Date
let curWaitTask;
let lastWaitTime = new Date(1970, 0, 1);
let func1 = function() {
if(curWaitTask) {
return curWaitTask;
}
if((new Date() - lastWaitTime) > TWENTY_MINUTES) {
lastWaitTime = new Date();
curWaitTask = func2().then(func3).then(func4);
return curWaitTask;
}
}
上面是一个即将过期的缓存方法。二十分钟缓存过期后对func1
的第一次调用将导致服务执行另一个异步操作来更新缓存。同时,可能会发生对func1
的其他调用,这将等待相同的缓存更新操作,而不是一次又一次地进行,直到设置缓存为止(由于所有调用的原因,一行多次)
当使用Babelwait
关键字提供的清晰性而不是一系列笨拙的.then()
时,是否有办法获得这种行为?实际上,它越来越难看。只需将“笨拙的然后链”包装在异步函数中,然后在其中使用等待
:
let curWaitTask;
let lastWaitTime = new Date(1970, 0, 1);
function func1() {
if (!curWaitTask && (new Date() - lastWaitTime) > TWENTY_MINUTES) {
lastWaitTime = new Date();
curWaitTask = doTask();
}
return curWaitTask;
}
async function doTask() {
return func4(await func3(await func2()));
}
(幸运的是?)在异步函数中不可能引用从当前调用创建的新承诺,因此在这里使用异步函数func1
并不明智。只需在异步函数中包装“笨拙的然后链”,并在其中使用等待:
let curWaitTask;
let lastWaitTime = new Date(1970, 0, 1);
function func1() {
if (!curWaitTask && (new Date() - lastWaitTime) > TWENTY_MINUTES) {
lastWaitTime = new Date();
curWaitTask = doTask();
}
return curWaitTask;
}
async function doTask() {
return func4(await func3(await func2()));
}
(幸运的是?)在异步函数中不可能引用从当前调用创建的新承诺,因此在这里使用异步函数func1
并不明智。您询问多个调用者是否可以订阅同一个异步函数,那么,让我们看看是否可以在func1
中解决这个问题,并保持它的异步(在Bergi的帮助下!):
curTask;
设lastTime=新日期(1970,0,1);
异步函数func1(){
如果(curTask&(新日期()-上次时间)<10000){
归来等待屈膝;
}
返回等待(curTask=(async()=>{
lastTime=新日期();
返回wait func4(wait func3(wait func2());
})());
}
我们可以等待承诺,而不仅仅是异步函数
我们将工作的重点放在第二个异步函数中,我们不会立即等待它,从而得到它的承诺,我们用它同步初始化curTask
。您询问多个调用者是否可以订阅同一个异步函数,那么让我们看看是否可以在func1
中解决这个问题并保持异步(在Bergi的帮助下!):
curTask;
设lastTime=新日期(1970,0,1);
异步函数func1(){
如果(curTask&(新日期()-上次时间)<10000){
归来等待屈膝;
}
返回等待(curTask=(async()=>{
lastTime=新日期();
返回wait func4(wait func3(wait func2());
})());
}
我们可以等待承诺,而不仅仅是异步函数
我们把工作的重点放在第二个异步函数中,我们不会立即等待它,从而得到它的承诺,我们同步初始化curTask
。我不确定我是否理解这个问题。难道你不能只写result=await operation()
?@Casey:Sayoperation()
需要很长的时间,比如1分钟。如果在5秒内调用wait operation()
行10次,它将执行整个1分钟的调用10次。但是在我给出的func1
示例中,长func2.then(func3)。然后(func4)
链只在第一次发生,并且以下9次调用func1()
将等待第一个承诺的结果。看到区别了吗?我明白了。但是你不能只发出curwaittask=wait func1()
然后循环吗?lastWaitTime
有没有更新过?如果缓存值和超时都没有过期,调用func1
应该怎么办?你的意思肯定是func2()notfunc2
?我不确定我是否理解这个问题。你能不能只写result=wait operation()
?@Casey:Sayoperation()
需要很长时间,比如1分钟。如果wait operation())
行在5秒钟内被调用10次,它将执行整个1分钟的调用10次。但是在我给出的func1
示例中,长func2.then(func3)。then(func4)
链只第一次发生,接下来的9次调用func1()
将等待第一个承诺的结果。看到区别了吗?我明白了。但是你不能只发出curwaittask=wait func1()
然后循环吗?lastWaitTime
有没有更新过?如果缓存值和超时都没有过期,调用func1
应该怎么办?你的意思肯定是func2()
notfunc2
?使用new Promise
和resolve
/reject
是非常值得怀疑的,而且非常容易出错。如果您真的需要这样的东西,我建议使用async
立即调用函数表达式。@Bergi毫无疑问是有问题的,但容易出错?它非常有用除了我没有将实际的异步函数传递给承诺构造函数之外,在异步函数中非常类似于承诺构造函数模式……也许我应该尝试一下……容易出错的原因有三:您可能忘记了try
/catch
(尤其是)如果合适,您可能会忘记解决承诺(但尝试返回),或者您可能会意外地尝试在调用resolve
之前等待curTask
。因此,经验法则是:不要在promise构造函数中使用async函数。只需执行curTask=(async()=>{…;return…;}())
@Bergi你说得对,这基本上完成了同样的事情,而且更简单。太好了,谢谢!使用新承诺
和解决
/拒绝
是很有问题的,而且很容易出错。我建议使用异步
立即调用