【问题标题】:How to throw an error in the outer function from an inner async function like setTimeout in JavaScript?如何从 JavaScript 中的 setTimeout 等内部异步函数在外部函数中抛出错误?
【发布时间】:2020-07-31 10:29:07
【问题描述】:

我想使用 firebase 身份验证登录到我的 react 本机应用程序。例如,要使用电子邮件和密码登录,我有以下功能,这基本上是一个 redux 操作:

export const userSignin = (email, password) =>
  async dispatch => {
    try {
      dispatch({ type: 'auth_attempt_started' })
      const user = await firebase.auth().signInWithEmailAndPassword(email.trim(), password)
      saveUserDataToAsyncStorage(user)
      if (!TASKS_SORT_BY && !TASKS_SORT_ORDER)
        dispatch(getTasksSortData(user.user.uid))
      if (!EMPLOYEES_SORT_BY && !EMPLOYEES_SORT_ORDER)
        dispatch(getEmployeesSortData(user.user.uid))
      if (!ACCOUNTS_SORT_BY && !ACCOUNTS_SORT_ORDER)
        dispatch(getAccountsSortData(user.user.uid))
      goToMain()
      setTimeout(() => {
        dispatch({
          type: 'user_signedin',
          payload: user
        })
      }, 100);
    }
    catch (err) {
      dispatch({
        type: 'auth_error',
        payload: err.toString()
      })
    }
  }

如果登录过程出现问题,此函数会引发错误。 问题是网速慢时,登录成功或失败的时间较长,有时30秒左右,对用户体验非常不利。

问题是:

如果登录过程未完成,我如何在有时可能 10 秒后抛出错误?

谢谢!

【问题讨论】:

    标签: javascript firebase react-native settimeout throw


    【解决方案1】:

    一般情况下可以通过setTimeout来实现。

    componentDidMount() {
      this.setTimeout( () => {
         this.doThisAfterTenSeconds();
      },10000);
    }
    
    doThisAfterTenSeconds() {
       // Do something
    }
    

    在这种特殊情况下,

    export const userSignin = (email, password) =>
      async dispatch => {
        try {
          // Auth attempt has started
          dispatch({ type: 'auth_attempt_started' })
    
          // Lets add a 10 second timeout
          let hasTimedOut = false
          setTimeout(() => {
              hasTimedOut = true
              // Display message here or throw "Connection timed out"
          }, 10000)
    
          // Now lets await the authentication
          const user = await firebase.auth().signInWithEmailAndPassword(email.trim(), password)
          // This code should not be run if auth attempt timed out. If we throw an error the check should not be neccessary...
          if (!hasTimedOut)
          {
             saveUserDataToAsyncStorage(user)
             if (!TASKS_SORT_BY && !TASKS_SORT_ORDER)
               dispatch(getTasksSortData(user.user.uid))
             if (!EMPLOYEES_SORT_BY && !EMPLOYEES_SORT_ORDER)
               dispatch(getEmployeesSortData(user.user.uid))
             if (!ACCOUNTS_SORT_BY && !ACCOUNTS_SORT_ORDER)
               dispatch(getAccountsSortData(user.user.uid))
             goToMain()
             setTimeout(() => {
               dispatch({
                 type: 'user_signedin',
                 payload: user
               })
             }, 100);
             }
           }
           catch (err) {
             dispatch({
               type: 'auth_error',
               payload: err.toString()
             })
           }
         }
    

    【讨论】:

    • 是的,但是如果我在 setTimeout 函数中抛出错误,主函数将继续运行,直到 const user = awai ... 完成;如果 promise 被解决,函数将结束,因为它不会执行下一个 if 块,但是如果 await 用户 promise 被拒绝,则会在主 catch 块中抛出另一个错误。如何处理这种情况?
    • 嗨@HadiYakhni,我做了一些研究,这似乎是您需要做的一个很好的解决方案:italonascimento.github.io/applying-a-timeout-to-your-promises 基本上使用 Promise.race(promiseA, promiseB),其中一个承诺是一个超时,另一个是你需要实现的实际承诺。
    • 谢谢@RandallValenciano,很好的解决方案!
    猜你喜欢
    • 1970-01-01
    • 2014-05-27
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多