node-fetch 在尝试从 api 获取令牌时的不正确行为

incorrect behaviour of node-fetch while trying to get token from an api

我想使用一些 node-fetch 代码连接到外部 api。我的代码首先发送登录详细信息并且应该从 api 接收令牌。然后这个token用于后面的所有通信。

这是代码:

import fetch from 'node-fetch';
function getTokenForAuth(info) {
    try {
        var auth_token = '';
        fetch(api_url + '/api/api-token/', {
            method: 'POST',
            body: JSON.stringify(info),

            headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            }
        })
        .then(function(res) {
            return res.json();
        })
        .then(function(json) {
            auth_token = json;
        })
        return auth_token.token;
    }

    catch (e) {
        console.log('[-] Error: Token Not Received');
        console.log('[!] Exception: ' + e);
    }
}

function getJSONFromRelativeURL(relativeURL, info) {
    return fetch(`${api_url}${relativeURL}`, {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Token ' + getTokenForAuth(info)
        }
    })
    .then(function(res) {
        console.log(res);
        return res.json();
    })
    .then(function(json) {
        console.log(json);
    })
}

getJSONFromRelativeURL() 函数的请求 headers 中,如果我对令牌进行硬编码,我会得到正确的结果。但是如果我 运行 现在的代码,我会收到一条错误消息:{ detail: 'Invalid token.' }.

我认为这是因为 fetch 函数中 promise 的异步性质,因此它有时无法在调用 getJSONFromRelativeURL() 之前及时发送令牌。我不确定这个假设,也不知道如何纠正。

还没有测试过,但它看起来像下面这样。对于错误处理,请在每个链的末尾使用 .catch(()=>{})。

   function getTokenForAuth(info) {

            var auth_token = '';
            return fetch(api_url + '/api/api-token/', {
                method: 'POST',
                body: JSON.stringify(info),

                headers: {
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                }
            })
            .then(function(res) {
                return res.json();
            })
           }


    function getJSONFromRelativeURL(relativeURL, info, token) {
        return fetch(`${api_url}${relativeURL}`, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Token ' + token
            }
        })
        .then(function(res) {
            console.log(res);
            return res.json();
        })
        .then(function(json) {
            console.log(json);
        })
    }


    getTokenForAuth(info)
    .then((token)=>{
      return getJSONFromRelativeURL(relativeURL, info, token)
    })

你的问题在这里:

.then(function(json) {
    auth_token = json;
})
return auth_token.token;

您的 return 声明在 Promise 链之外。这意味着,在您点击 return 时,fetch 请求还没有机会 运行。您基本上只是告诉 fetch Promise 链 在它 return.[=17= 时做什么]

基本上

I think this is because of async nature of the promise in the fetch function, because of which it sometimes isnt able to send the token in time before the getJSONFromRelativeURL() gets called.

100% 正确。

你需要做的是稍微重组一下:

function getTokenForAuth(info) {
  return fetch(api_url + "/api/api-token/", {
    method: "POST",
    body: JSON.stringify(info),

    headers: {
      "Content-Type": "application/json",
      Accept: "application/json"
    }
  }).then(function(res) {
    return res.json();
  });
}

function getJSONFromRelativeURL(relativeURL, info) {
  return getTokenForAuth(info)
    .then(function(token) {
      return fetch(`${api_url}${relativeURL}`, {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Token ${token}`
        }
      });
    })
    .then(function(res) {
      console.log(res);
      return res.json();
    })
    .then(function(json) {
      console.log(json);
    });
}