努力让异步函数等待数据库响应

时间:2021-02-16 15:53:35

标签: javascript reactjs mongodb asynchronous

预先感谢您抽出时间帮助我。

我正在尝试使用 MongoDB 后端登录用户,我调用了一个异步函数来进行 fetch 调用,如果我收到 200 响应代码,则返回登录令牌。 :

_initialize = async userAddress => {

    const token = await login(userAddress);
    console.log("TOKEN:", token);

    // Do other stuff with the token
  }

登录功能如下所示:

export const login = async address => {
    const requestOptions = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ address })
      };
  
      let responseCode;
      fetch(`___ENDPOINT___`, requestOptions)
        .then(response => {
          responseCode = response.status;
          return(response.json());
        })
        .then(data => {
          if(responseCode == 200){
            console.log(data.token)
            const token = data.token;
            return token;
          }
          if(responseCode == 400){
            if(data.message === "User not yet registered"){
              // Do nothing
              return;
            }
          }
        })
        .catch(error => {
          console.log(error)
        });
}

我遇到的问题是没有等待 await login() 调用,而是 token 被控制台记录为 undefined

如果我删除 await 关键字,我收到的令牌为:

Promise {<fulfilled>: undefined}
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: undefined

我不明白,为什么令牌未定义?如果我在 .then 块中记录令牌,它会成功返回,但这只会在令牌被打印为 initialize 函数中的 undefined 之后发生。

就像异步函数初始化不等待异步登录函数一样?

非常感谢您的帮助,再次感谢您的时间。

2 个答案:

答案 0 :(得分:2)

您的 login 函数不返回承诺。事实上,它根本不返回任何东西。查看评论:

export const login = async address => {
    const requestOptions = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ address })
    };

    // Note: Don't catch erros in this function, let them propagate
    // so the caller knows what happened
  
    // No need for `.then`/`.catch` in an `async` function, use `await`

    // Wait for the initial resaponse
    const response = await fetch(`___ENDPOINT___`, requestOptions);
    const responseCode = response.status;
    if (!response.ok) {
        // Not an OK reseponse
        if (responseCode == 400) {
            // Parse the body to see if we have the message
            const data = await response.json();
            if (data.message === "User not yet registered") {
                // Do nothing
                return;
            }
        }
        throw new Error("HTTP error " + responseCode);
    }

    // OK response, read the data from the body, this is also async
    const data = await response.json();
    return data.token;
};

请注意,如果响应代码为 400 并且该响应的正文是定义了 {{1 }} 属性,文本为 loginundefined 需要检查一下。此外,message 应该处理来自 "User not yet registered" 的任何错误。

答案 1 :(得分:0)

如果有人知道为什么上面的代码不起作用,那仍然非常有用,但是我想出了一个解决方案:

export const login = async address => {
    const requestOptions = {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ address })
      };

      const response = await fetch(`___ENDPOINT___`, requestOptions)
      const data = await response.json();

      const responseCode = response.status;
      if(responseCode == 200){
        console.log(data.token)
        const token = data.token;
        return token;
      }
      if(responseCode == 400){
        if(data.message === "User not yet registered"){
          // Do nothing
          return;
        }
      }
}