JavaScript是否有多个等待?

dea*_*904 3 javascript admob reactjs react-native

我有一个React Native App,当用户单击一个按钮时,我调用一个函数,该函数_openInterstitial返回2个Promise。

代码如下:

_openInterstitial = async () => {
    try {
      await AdMobInterstitial.requestAdAsync()
      await AdMobInterstitial.showAdAsync()
    } catch (error) {
      console.error(error)
    }
  }
Run Code Online (Sandbox Code Playgroud)

当我快速点击按钮两次时,它返回此错误

已经在请求广告,请等待之前的承诺。

我如何履行await先前的承诺?

我是否需要将另一个带await出另一个try..catch区块?

还有其他更简单的方法吗?

T.J*_*der 5

您基本上有三个选择:

  1. 在上一个通话结束之前,不允许通话,或者
  2. 将通话排队,仅在前一个通话结束时才开始通话,或者
  3. _openInterstitial如果仍未完成,请致电以返回上次致电的承诺。因此,通话可能不会打开新的插页式广告,而可能会返回前一次通话的承诺。

对于#1,您至少有两个选择:

如果调用_openInterstitial来自UI组件回调,则取决于您所响应的事件的类型,您可以通过Max Svid的answer中setState所示禁用该UI组件。例如,如果它是一个按钮而您正在响应,那肯定可以正常工作。(我与Dan Abramov进行了核对。)不能保证所有事件(例如)都可以,但可以保证是类似的。这里列出了可以保证的内容。clickmousemoveclickinteractiveEventTypeNames

如果没有,您将需要记住自己正在执行此操作,并避免启动另一个操作,例如:

_openInterstitialEnabled = true;
_openInterstitial = async () => {
  if (this._openInterstitialEnabled) {
    try {
      this._openInterstitialEnabled = false;
      await AdMobInterstitial.requestAdAsync();
      await AdMobInterstitial.showAdAsync();
      this._openInterstitialEnabled = true;
    } catch (error) {
      console.error(error);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,除了上面的防护措施之外,您还应该禁用触发此功能的UI。

对于#2(排队),请记住先前的承诺并等待其完成,然后再开始下一个操作,例如:

_lastOpenInterstitial = Promise.resolve();
_openInterstitial = () => {
  return this._lastOpenInterstitial = this._openInterstitialWorker();
};
_openInterstitialWorker = async () => {
  try {
    await this._lastOpenInterstitial;
    await AdMobInterstitial.requestAdAsync();
    await AdMobInterstitial.showAdAsync();
  } catch (error) {
    console.error(error);
  }
};
Run Code Online (Sandbox Code Playgroud)

或更简单地说:

_lastOpenInterstitial = Promise.resolve();
_openInterstitial = () => {
  return this._lastOpenInterstitial = this._lastOpenInterstitial
    .then(AdMobInterstitial.requestAdAsync) // Assuming it doesn't care about `this`, use an arrow function wrapper if it does
    .then(AdMobInterstitial.showAdAsync)    // Same assumption
    .catch(error => { console.error(error); });
};
Run Code Online (Sandbox Code Playgroud)

或者如果您想async尽早返回功能:

_lastOpenInterstitial = Promise.resolve();
_openInterstitial = () => {
  return this._lastOpenInterstitial = this._lastOpenInterstitial.then(async() => {
    await AdMobInterstitial.requestAdAsync();
    await AdMobInterstitial.showAdAsync();
  }).catch(error => { console.error(error); });
};
Run Code Online (Sandbox Code Playgroud)

在所有这些中,我都假定这属于某种类,并且它们是使用类字段语法的公共属性声明,但是如果我猜错了,很容易根据需要进行调整。

#3涵盖在SomePerformance的答案中