【问题标题】:How to make the API call to wait until we get required data?如何让 API 调用等到我们获得所需的数据?
【发布时间】:2021-11-06 17:05:04
【问题描述】:

我正在使用 React Native 和 Redux。在 Redux 的初始状态下,emailExists 设置为null

const INITIAL_STATE = {
  // ...
  emailExists: null,
};

注册用户时。首先,我通过向服务器发送请求来检查用户是否已经存在,如果用户已经存在,我会显示一个 toast。

const registerUser = (values, actions) => {
  checkEmail(values.userEmail);   // takes time to get result of `emailExists`
  
  if (emailExists) {            // `emailExists` is now `null` couldn't wait for response
     toastRef.current.show("Email already exists!");
     return;
  }
}

checkEmail 代码如下:

function checkEmail(data) {
  return (dispatch) => {
    return api_request
      .post("register/check/email", { email: data })
      .then((res) => {
        dispatch(emailExists(res.data.exists));
        dispatch(authError("Email already exists"));
      })
      .catch((err) => {
        console.log(`err`, err);
      });
  };
}

在调度dispatch(emailExists(res.data.exists)); 之后,emailExists 将是truefalse,但问题是由于请求需要时间从服务器获取数据,所以在第一次加载应用程序时总是设置emailExistsnull。这意味着以下条件在第一次加载时总是错误的:

if (emailExists) {
   toastRef.current.show("Email already exists!");
   return;
}
function emailExists(payload){
  return {
    type: userConstants.EMAIL_EXISTS, 
    emailExists: payload
  }
}

我该如何解决这个问题?

谢谢你

【问题讨论】:

    标签: reactjs react-native asynchronous redux async-await


    【解决方案1】:

    您可以像这样修改函数以获得预期的结果。

    function checkEmail(data,callback) {
      return (dispatch) => {
        return api_request
          .post("register/check/email", { email: data })
          .then((res) => {
           // dispatch(emailExists(res.data.exists)); // You don't need this redux approach now because it will take time and will give you the same error
            dispatch(authError("Email already exists"));
            callback && callback(res.data.exists) // I am assuming here you got the response that email alreay exists and its value is true.
          })
          .catch((err) => {
            console.log(`err`, err);
          });
      };
    }
    

    现在在 API 请求完成并获得响应时获取回调。

        const registerUser = (values, actions) => {
    
          const callback = (isEmailExists) => {
           //Here you will get the value of the checkemail API (true/false)
           //Now do any action in this block of functions
           if (isEmailExists) {    
            toastRef.current.show("Email already exists!");
            return;
            }
          }
    
          checkEmail(values.userEmail,callback);
          
    
        }
    

    【讨论】:

    • 感谢您的回答
    【解决方案2】:

    Mantu 的答案是一种解决方案。对于这个用例,我更喜欢使用 async/await。 dispatch() 返回操作创建者返回的函数返回的任何内容。因此,在这种情况下,您将返回一个承诺,这意味着您可以等待您的 dispatch(checkEmail(values.userEmail)) 呼叫。

    你需要从 promise 中返回 email 是否存在,否则即使你等待 checkEmail 操作完成,当你访问它时 emailExists 也不会是最新的(因为使用 useSelector 将不得不重新渲染组件以反映商店中的更新)。

    const registerUser = async (values, actions) => {
      const emailExists = await checkEmail(values.userEmail);
      
      if (emailExists) {
         toastRef.current.show("Email already exists!");
         return;
      }
    }
    
    function checkEmail(data) {
      return (dispatch) => {
        return api_request
          .post("register/check/email", { email: data })
          .then((res) => {
            dispatch(emailExists(res.data.exists));
            dispatch(authError("Email already exists"));
            return res.data.exists;
          })
          .catch((err) => {
            console.log(`err`, err);
          });
      };
    }
    

    如果不想从 promise 中返回属性,则需要通过 store.getState() 同步从 store 中获取值:

    const registerUser = async (values, actions) => {
      await checkEmail(values.userEmail);
      const emailExists = selectEmailExists(store.getState());
      if (emailExists) {
         toastRef.current.show("Email already exists!");
         return;
      }
    }
    

    【讨论】:

    • 感谢您的回答
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 2019-10-09
    • 1970-01-01
    • 1970-01-01
    • 2017-09-27
    • 2020-02-09
    相关资源
    最近更新 更多