【问题标题】:incorrect behaviour of node-fetch while trying to get token from an api尝试从 api 获取令牌时节点获取的错误行为
【发布时间】:2018-01-13 09:16:27
【问题描述】:

我想使用一些节点获取代码连接到外部 api。我的代码首先发送登录详细信息,并且应该从 api 接收令牌。然后这个令牌用于以后的所有通信。

代码如下:

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

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

【问题讨论】:

  • getTokenForAuth 返回一个承诺对象。所以你没有设置授权头。尝试控制它,您将看到一个对象而不是令牌。必须调用getTokenForAuth 并在其中.then() 调用getJSONFromRelativeURL 函数。这样您就可以将令牌作为字符串。还必须从 then 内部而不是外部返回令牌。
  • 反正我是第一个回答的。是什么让您不理解我的回答,以便我改进?
  • 我刚刚选择了另一个答案,因为它的代码更好地放在一起,他还回答了我的假设(我不确定)。我认为,回首往事,他的答案也以更好的方式与逻辑流程组合在一起(向我展示我做错了什么,然后逐步回答)。

标签: node.js api asynchronous promise node-fetch


【解决方案1】:

你的问题在这里:

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

您的 return 语句位于 Promise 链之外。这意味着,在您点击return 时,fetch 请求甚至还没有机会运行。你基本上只是告诉fetch Promise 链做什么当它确实返回时要做什么。

本质上

我认为这是因为 fetch 函数中 promise 的异步性质,因此它有时无法在调用 getJSONFromRelativeURL() 之前及时发送令牌。

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);
    });
}

【讨论】:

    【解决方案2】:

    尚未对其进行测试,但它看起来类似于以下内容。对于错误处理,在每个链的末尾使用 .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)
        })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-29
      • 2016-07-26
      • 1970-01-01
      • 2022-06-23
      • 2019-06-23
      • 2020-06-09
      • 1970-01-01
      • 2020-09-11
      相关资源
      最近更新 更多