fetch() 意外的输入结束

IT技术 javascript json cors fetch-api
2021-03-09 13:18:59

我正在使用 fetch() 从 api 服务器获取数据。我的错误是这样的:

Uncaught (in promise) SyntaxError: Unexpected end of input at 
  fetch.then.blob.

你能告诉我我做错了什么吗?

const weatherAPi ='https://www.metaweather.com/api/location/523920';
fetch(weatherAPi, {
  mode: 'no-cors'
}).then(blob => blob.json())
  .then(data => console.log(data))
6个回答

不透明的响应

no-cors跨域资源请求的响应具有 'opaque' 响应类型如果您在尝试将其转换为 JSON 之前记录响应,您将看到一种“不透明”。

whatwg.org 上的提取规范中所述,不透明类型被列为“严格限制”

不透明过滤响应是类型为“不透明”的过滤响应,url列表为空列表,状态为0,状态消息为空字节序列,头部列表为空,正文为空,尾部为空。

当类型为 opaque 时,当前无法读取它们,如Google's docs on the opaque type 所述

不透明响应是针对不同来源的资源发出的请求,该请求不返回 CORS 标头。对于不透明的响应,我们将无法读取返回的数据或查看请求的状态,这意味着我们无法检查请求是否成功。使用当前的 fetch() 实现,不可能从 window 全局范围请求不同来源的资源。

在您的服务器上启用 CORS 支持

这可以依赖于环境或依赖于语言。例如,您可以通过更改服务器配置来更改 Nginx 环境中的 CORS 设置,或者您可以在应用程序代码中指定标头,例如在 PHP 中。

我强烈建议阅读有关 CORS 请求Access-Control-Allow-OriginMozilla 文档

PHP中的一个例子:

<?php
header("Access-Control-Allow-Origin: *");  // "*" could also be a site such as http://www.example.com
通常,当服务器抛出错误并且 CORS 与此无关时,您会收到 CORS 错误。所以,如果我知道我的 CORS 设置是正确的,我总是开始检查服务器端代码是否有问题。
2021-04-17 13:18:59
它的解决方案是什么......如果我删除no-cors然后它会引发交叉原点错误
2021-04-19 13:18:59
@AnthonyWinzlet,您需要更新您尝试从中请求信息的服务器上的 CORS 标头。出于安全目的,这些 CORS 策略就位。这是一个相当长的阅读,但这里有一个关于 CORS 请求的很好的资源
2021-05-16 13:18:59

我有同样的问题。在我的情况下,它不是由解决方案指出的“不透明”的响应类型引起的。此代码会导致响应为空的错误,因为 'fetch' 不接受具有空正文的响应:

return fetch(urlToUser, parameters)
.then(response => {
  return response.json()
})
.then((data) => {
  resolve(data)
})
.catch((error) => {
  reject(error)
})

相反,在我的情况下,这效果更好:

return fetch(urlToUser, parameters)
.then(response => {
  return response.text()
})
.then((data) => {
  resolve(data ? JSON.parse(data) : {})
})
.catch((error) => {
  reject(error)
})

即使是空的正文,获取文本也不会出现错误。然后检查数据是否存在并解决。我希望它有帮助:-)

Github 的 fetch polyfill团队也推荐了相同的解决方案:github.com/github/fetch/issues/268#issuecomment-176544728
2021-04-17 13:18:59
我喜欢这个解决方案。我遇到了同样的问题,我的一些 REST 响应没有正文,而核心服务需要 JSON。这已经很好地解决了!谢谢。
2021-04-17 13:18:59
response.text() 对我来说是空的
2021-05-11 13:18:59

很多很好的回应,但我选择了这个:

      const response = await fetch(url, {
        method: 'GET',
        headers: {
          Authorization: 'Bearer ' + accessToken
        }
      });
      const string = await response.text();
      const json = string === "" ? {} : JSON.parse(string);
      return json;
撞!这个是赢家!
2021-05-08 13:18:59

您需要在 php 或其他服务器端点的标头中包含以下行:

<?php
header('Access-Control-Allow-Origin: *');
//or
header('Access-Control-Allow-Origin: http://example.com');

// Reading JSON POST using PHP
$json = file_get_contents('php://input');
$jsonObj = json_decode($json);

// Use $jsonObj
print_r($jsonObj->message);

...
// End php
?>

使用 POST 请求获取代码的工作模型是:

const data = {
        optPost: 'myAPI',
        message: 'We make a research of fetch'
    };
const endpoint = 'http://example.com/php/phpGetPost.php';

fetch(endpoint, {
    method: 'POST',
    body: JSON.stringify(data)
})
.then((resp) => resp.json())
.then(function(response) {
    console.info('fetch()', response);
    return response;
});
您也可以使用在线 cors 代理cors-anywhere.herokuapp.com来规避此问题,而无需自己编写 PHP。
2021-04-30 13:18:59

(对于后来来但处理这个问题“JSON 输入意外结束”的人)

很多时候的问题是服务器错误或只是无效的 URL,但您看不到它,因为互联网上的所有示例fetch都缺少一个重要的部分 - 服务器或网络故障。

我认为如何处理的正确方法fetch是在转换为json.

检查then示例中it.ok测试的第一个部分

async function fetchData() {
    return await fetch('https://your-server.com/some-NOt-existing-url/')
        .then(it => {
            if (!it.ok) {
                throw `Server error: [${it.status}] [${it.statusText}] [${it.url}]`;
            }
            return it.json();
        })
        .then(receivedJson => {
            // your code with json here...
        })
        .catch(err => {
            console.debug("Error in fetch", err);
            setErrors(err)
        });
}

(注意:it只是从 Kotlin 借来的命名约定,它使 TypeScript/JavaScript 代码更短。它是表达式左侧任何内容的别名,因此在这种情况下为response