【问题标题】:How does this code work in this specifics regarding async wait此代码如何在有关异步等待的细节中工作
【发布时间】:2020-10-28 06:13:30
【问题描述】:

我学习了一些 React 和 Redux 并且有一个初学者问题。

在下面的 GitHub 代码中,有两个方法调用 getInitUsers()getMoreUsers()
Here is Original GitHub code for the below code

....
useEffect(() => {
    const getUsers = async () => {
        await getInitUsers();
    }
    getUsers();
}, [getInitUsers]);

const addMoreUsers = () => {
    if(!isGettingMoreUsers) {
        getMoreUsers(prevDoc);
    }
}

....

const mapDispatchToProps = dispatch => ({
    getInitUsers: () => dispatch(asyncGetInitUsers()),
    getMoreUsers: prevDoc => dispatch(asyncGetMoreUsers(prevDoc))
})

...

上述getInitUsers()getMoreUsers()的Redux动作是这两个: Here is the original GitHub code for the below code

export const asyncGetInitUsers = () => {
    return async dispatch => {
        try {
            dispatch(getUsersStart());
            const usersRef = firestore.collection("users").orderBy("registrationDate", "desc").limit(30);
            usersRef.onSnapshot(docSnapShot => {
                let users = [];
                docSnapShot.docs.forEach(doc => {
                    users.push({id: doc.id, data: doc.data()});
                });
                dispatch(getUsersSuccess(users));
                const lastDoc = docSnapShot.docs[docSnapShot.docs.length - 1];
                dispatch(setPrevDoc(lastDoc));
            });

        } catch (errorMsg) {
            dispatch(getUsersFailure(errorMsg));
        }
    }
}

export const asyncGetMoreUsers = prevDoc => {

    return async dispatch => {
        try {
            dispatch(getMoreUsersStart());

            const usersRef = firestore.collection("users").orderBy("registrationDate", "desc").startAfter(prevDoc).limit(30);
            usersRef.onSnapshot(docSnapShot => {
                let users = []
                docSnapShot.docs.forEach(doc =>{
                    users.push({id: doc.id, data: doc.data()})
                });
                dispatch(getMoreUsersSuccess(users));
                const lastDoc = docSnapShot.docs[docSnapShot.docs.length - 1];
                dispatch(setPrevDoc(lastDoc));
            });
        } catch (e) {
            dispatch(getMoreUsersFailure(e));
        }
    }
}

我了解将getInitUsers() 放在useEffect() 中会使其在组件创建时运行一次。我想问的是这个await在这一行做了什么:

 await getInitUsers();

如果您查看getMoreUsers(),它没有await,如果您查看asyncGetInitUsers()asyncGetMoreUsers() 以上两个动作,它们具有相同的逻辑并以:

 return async dispatch => {...

那么这里有什么区别呢? getInitUsers()getMoreUsers()??
我创建了一个CodeSandbox 来尝试理解await

【问题讨论】:

    标签: reactjs redux async-await


    【解决方案1】:

    在这种情况下,await 没有什么不同,实际上使用 async await 没有任何意义,因为您在 await 之后没有做任何事情或从中返回值。

    因此,getInitUsers 位可以简化为:

    useEffect(() => {
        getInitUsers();
    }, [getInitUsers]);
    

    例如,如果您想在 getInitUsers 完成后运行一些代码。例如,加载布尔值:

    const [loading, setLoading] = useState(false);
    useEffect(() => {
      setLoading(true);
      const getUsers = async () => {
        await getInitUsers();
        setLoading(false);
      };
      getUsers();
    }, [getInitUsers]);
    
    

    虽然由于代码的简单性,这可以通过直接使用 Promise 来简化:

    const [loading, setLoading] = useState(false);
    useEffect(() => {
      setLoading(true);
      getInitUsers().then(() => {
        setLoading(false);
      });
    }, [getInitUsers]);
    
    

    有关异步等待的一些文档及其对我们的作用:https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await,但这里有一些介绍:

    本质上,async/await 是允许在 JS 中更轻松的异步流程的功能组合。

    这些特性基本上充当了 Promise 之上的语法糖, 使异步代码更易于编写和以后阅读。他们 使异步代码看起来更像老式同步代码,所以它们是 很值得学习。本文为您提供了您需要了解的内容。

    async 函数总是返回一个promise,并且它们在被调用的那一刻就这样做了。 当 async 函数完成执行时,该 Promise 将解析为从它返回的值(如果没有返回则未定义)或被错误拒绝。

    await 仅适用于异步函数(尽管在第 3 阶段有针对Top Level Await 的提案)。 await 接受一个 Promise 并等待它被解决或拒绝,然后再继续执行和解开 Promise。

    所以,没有 async/await,你需要使用 Promise 的 .then.catch 函数,但是使用 async/await,你可以做很多事情来减少回调地狱。

    这里有一些非常人为的示例来展示如何使用 async/await 语法糖可以使代码更易于阅读和推理。尽管最大的危险还在于 async/await 使代码看起来是同步的,尽管实际上并非如此。

    // Setting up a couple promises
    let promise = new Promise(resolve => resolve(42));
    let promise2 = new Promise(resolve => resolve(8));
    
    // Using promises to multiply them together
    Promise.all([promise, promise2])
      .then(([value, value2]) => value * value2)
      .then(value => console.log('promises', value))
    
    
    // Setting up a couple promises
    let promise3 = new Promise(resolve => resolve(42));
    let promise4 = new Promise(resolve => resolve(8));
    
    // Using async/await to multiply them together
    (async() => {
      let value = await promise3 * await promise4;
      console.log('async/await', value);
    })()

    【讨论】:

      猜你喜欢
      • 2013-07-03
      • 2014-06-06
      • 1970-01-01
      • 2014-12-03
      • 2023-03-27
      • 2017-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多