如何在更改网址之前等待成功的异步操作?

时间:2020-06-25 05:55:29

标签: javascript reactjs asynchronous redux async-await

所以我正在使用弹出窗口使用Firebase登录我的用户:

const loginToApp = (provider) => {
    firebaseApp
        .auth()
        .signInWithPopup(provider)
        .then(async (result) => {
            if (result.additionalUserInfo.isNewUser) {
                // problem is this line
                await setNewUserInformation(result.user.uid)
            }
            const { user } = result
            setUser(user)
            // and this line
            window.location.href = 'newRoute'
        })
        .catch((error) => {
            console.log('ERROR:', error)
        })
}

因此,如果我删除window.location.href = 'visited',则一切正常,并将其设置为Firebase。我可能在做一些愚蠢的事情,但是我想不通如何等待此功能启动setNewUserInformation并完成操作,然后再移至新页面?

功能代码:

export const setNewUserInformation = (userId) => {
    return {
        type: 'SET_NEW_USER_INFORMATION',
        userId,
    }
}

然后有一个可观察到的redux观看史诗:

return action$.pipe(
    ofType('SET_NEW_USER_INFORMATION'),
    mergeMap((action) => {
        return from(
            firebaseApp.database().ref(firebaseRef).update(userInformation),
        ).pipe(
            mergeMap(() => {
                return [updatedUserInformationSuccess()]
            }),
            catchError((error) => of(updatedUserInformationFailure(error))),
        )
    }),
)

4 个答案:

答案 0 :(得分:1)

setNewUserInformation()是动作创建者,已同步。您不需要等待它,因为它不会返回任何对您的逻辑有用的信息。您需要做的是将window.location.href = 'newRoute'移动到单独的逻辑,并使它依赖于操作创建者updatedUserInformationSuccess()返回的状态和updatedUserInformationFailure(错误)。如果您的组件正常运行,请将此逻辑放在useEffect中。如果它是类组件,请使用ComponentDidUpdate生命周期方法。

答案 1 :(得分:0)

如下使用

const loginToApp = (provider) => {
firebaseApp
    .auth()
    .signInWithPopup(provider)
    .then(async (result) => {
        new Promise((resolve, reject) => {
             if (result.additionalUserInfo.isNewUser) {
                // problem is this line
                setNewUserInformation(result.user.uid)
            }
           const { user } = result
           resolve(user)
        }).then((user)=>{
          setUser(user)
          // and this line
          window.location.href = 'newRoute'
        })
       
    })
    .catch((error) => {
        console.log('ERROR:', error)
    })
  }

答案 2 :(得分:0)

由于then,您可以返回一个Promise,稍后再解决。我们可以像下面这样重新编写上面的代码:

const loginToApp = (provider) => {
    firebaseApp
        .auth()
        .signInWithPopup(provider)
        .then((result) => {
            if (result.additionalUserInfo.isNewUser) {
                // return for next resolve function
                return setNewUserInformation(result.user.uid).then(() => result); 

            }
            return result;
        })
        .then((result) => {
            // after all above promises resolve
            const { user } = result
            setUser(user)
            // and this line
            window.location.href = 'newRoute'
        })
        .catch((error) => {
            console.log('ERROR:', error)
        })
}

答案 3 :(得分:0)

您在使用React吗? 如果是,那么在成功执行操作后,您可以简单地使用didUpdate Cycle路由到新的url。用道具检查将ComponentDidUpdate下的“ window.location.href ='newRoute'”移动。