如何使用 fetch 处理响应 .json 和 .text?

Ven*_*sky 13 javascript fetch es6-promise

我正在获取一个返回 json 的 API,但是当它出现错误时,它只返回一个文本(在带有 express 的节点中,返回结果为.json({}),错误为.send('string')),但是我无法修改 API

所以我试图制作一些读取 json 的东西,但如果它是一个文本,它将进入.catch错误所在的文本。

这是我尝试过但没有成功的方法。

fetch(apiUrl)
    .then(res => {
        try {
            let json = res.json()
            return json
        } catch (error) {
            return new Promise((resolve, reject) => reject(res.text()))
        }
    })
    .then(res => {
        // get result from res.json() **res == res.json**
    })
    .catch(error => {
        // get result from res.text() **res == res.text**
    })
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?如何获得res.json()在未来.then(),但如果失败,得到res.text().catch

编辑:

我想获得.text.catch。我不知道为什么,但投掷res.text()不起作用。

Krz*_*ski 10

另一种方法是最初将所有内容格式化为文本,然后才尝试解析它,同时在解析问题的情况下抛出错误。

fetch("http://maps.googleapis.com/maps/api/geocode/json?address=google")
    .then(res => res.text())
    .then(body => {
        try {
            return JSON.parse(body);
        } catch {
            throw Error(body);
        }
    })
    .then(console.log)
    .catch(console.error);

fetch("http://maps.googleapis.com/maps/api/geocode/xml?address=google")
    .then(res => res.text())
    .then(body => {
        try {
            return JSON.parse(body);
        } catch {
            throw Error(body);
        }
    })
    .then(console.log)
    .catch(console.error);
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个解决方案。 (2认同)

Igo*_*nko 9

理想情况下,您的客户端应用程序应该知道预期的响应类型并具有调用适当方法的静态代码。


处理您的情况的另一种方法是检查响应contentType和调用.json().text()取决于特定的响应标头值。

handleResponseStatusAndContentType(response) {
  const contentType = response.headers.get('content-type')!;

  if (response.status === 401) throw new Error('Request was not authorized.');

  if (contentType === null) return Promise.resolve(null);
  else if (contentType.startsWith('application/json;')) return response.json();
  else if (contentType.startsWith('text/plain;')) return response.text();
  else throw new Error(`Unsupported response content-type: ${contentType}`);
}
Run Code Online (Sandbox Code Playgroud)

用法:

return fetch(
  url,
  requestInit,
)
.then(response => handleResponseStatusAndContentType(response))
.catch(error => {
  console.error(error);
  return error;
});
Run Code Online (Sandbox Code Playgroud)

  • 新 Promise 的语法是什么?它看起来像模板/泛型,但 JS 没有。 (2认同)