Javascript 多个调用者可以使用Babel Wait关键字订阅同一个异步函数吗?

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

如果函数返回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();
    curWaitTask = func2().then(func3).then(func4);
    return curWaitTask;
  }
}
上面是一个即将过期的缓存方法。二十分钟缓存过期后对
func1
的第一次调用将导致服务执行另一个异步操作来更新缓存。同时,可能会发生对
func1
的其他调用,这将等待相同的缓存更新操作,而不是一次又一次地进行,直到设置缓存为止(由于所有调用的原因,一行多次)

当使用Babel
wait
关键字提供的清晰性而不是一系列笨拙的
.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:Say
operation()
需要很长的时间,比如1分钟。如果在5秒内调用
wait operation()
行10次,它将执行整个1分钟的调用10次。但是在我给出的
func1
示例中,长
func2.then(func3)。然后(func4)
链只在第一次发生,并且以下9次调用
func1()
将等待第一个承诺的结果。看到区别了吗?我明白了。但是你不能只发出
curwaittask=wait func1()
然后循环吗?
lastWaitTime
有没有更新过?如果缓存值和超时都没有过期,调用
func1
应该怎么办?你的意思肯定是
func2()
not
func2
?我不确定我是否理解这个问题。你能不能只写
result=wait operation()
?@Casey:Say
operation()
需要很长时间,比如1分钟。如果
wait operation())
行在5秒钟内被调用10次,它将执行整个1分钟的调用10次。但是在我给出的
func1
示例中,长
func2.then(func3)。then(func4)
链只第一次发生,接下来的9次调用
func1()
将等待第一个承诺的结果。看到区别了吗?我明白了。但是你不能只发出
curwaittask=wait func1()
然后循环吗?
lastWaitTime
有没有更新过?如果缓存值和超时都没有过期,调用
func1
应该怎么办?你的意思肯定是
func2()
not
func2
?使用
new Promise
resolve
/
reject
是非常值得怀疑的,而且非常容易出错。如果您真的需要这样的东西,我建议使用
async
立即调用函数表达式。@Bergi毫无疑问是有问题的,但容易出错?它非常有用除了我没有将实际的异步函数传递给承诺构造函数之外,在异步函数中非常类似于承诺构造函数模式……也许我应该尝试一下……容易出错的原因有三:您可能忘记了
try
/
catch
(尤其是)如果合适,您可能会忘记解决承诺(但尝试返回),或者您可能会意外地尝试在调用
resolve
之前等待curTask
。因此,经验法则是:不要在promise构造函数中使用
async函数。只需执行
curTask=(async()=>{…;return…;}())
@Bergi你说得对,这基本上完成了同样的事情,而且更简单。太好了,谢谢!使用
新承诺
解决
/
拒绝
是很有问题的,而且很容易出错。我建议使用
异步
立即调用