UnhandledPromiseRejectionWarning: FetchError: invalid json response body at

UnhandledPromiseRejectionWarning: FetchError: invalid json response body at

获取错误:

UnhandledPromiseRejectionWarning: FetchError: invalid json response body at {url}
reason: Unexpected token < in JSON at position 0

我的代码:

const fetch = require('node-fetch');

const url = 'Reeeealy long url here';

fetch(url)
  .then(res => res.json())
  .then(console.log);

如果 url 长于 ~8k+ 个字符 api returns

400 Bad Request
Request Header Or Cookie Too Large
nginx

显然我无法控制 api。

我能做些什么来防止这种情况发生?

url结构:

1) 域

2) api 版本

3) 端点

4) 请求内容(最长的部分)

5) id在最后

看起来像这样:https://example.com/v1/endpoint/query?query=long_part_here&ids=2145132,532532,535

如果预期 'long_part' 很长,这听起来像是设计不佳的 api。它应该使用 POST 而不是 GET 请求,以便可以在 body 对象中发送长数据集。你能看到 API 是否允许 POST 版本的端点允许吗?

如果没有 POST 可用,并且您无法控制 API,那么您的选择余地不大。我唯一能想到的是,如果可行的话,您将请求分成多个单独的端点调用(可能每个 id 一个),并且会导致每个请求的 url 大小更短。

多次调用

如果您能够执行多个较小的请求,代码可能如下所示:

const urls = ["firstUrl","secondUrl","nthUrl"];
let combined = {};
for (const url of urls) {
  fetch(url)
    .then(res => res.json())
    .then(json => combined = {...combined, ...json};
}
console.log(combined);

这假定将所有结果合并到一个对象中是合理的。如果它们应该保持不同,您可以像这样更改最后一个 then

.then(json => combined = {...combined, {`url${count}`: json}};

其中 count 是每次递增的整数,combined 看起来像

{url1: {/*json from url1*/}, url2: {/*json from url2*/}, ...}

错误处理

为了更优雅地处理错误,您应该在假设返回结果之前检查结果 JSON。您遇到了 JSON 解析错误,因为返回的数据不是 JSON。它是 HTML,所以当它以 < 开始时失败了。你可以这样做:

fetch(url)
  .then(res => {
    if (res.resultCode == "200") return res.json();
    return Promise.reject(`Bad call: ${res.resultCode}`);
  })
  .then(console.log);