TypeError:无法获取,网络控制台中出现 400 错误,但不是异常

问题描述 投票:0回答:1

我正在尝试调用 Google Drive REST API 以使用

fetch
API 从浏览器上下文上传文件,但无法克服一个奇怪的错误。

TypeError: Failed to fetch

查看有关该主题的其他帖子,有些指出 CORS 失败,但很难从该消息中准确确定错误是什么。奇怪的是,查看 Chrome 开发工具的“网络”选项卡会讲述一个不同的故事:

enter image description here

现在我将第一个承认我发送格式错误的请求的可能性(很高?),但是在没有任何错误消息的情况下确定请求格式错误也非常困难。

令我更加困惑的是,为什么

fetch
调用被拒绝(用
await
抛出错误),而不是通过 400 响应来解决。

拨打电话的代码非常基本:

await fetch(`https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart`, options);

options
对象是非常样板的,只设置诸如
Authorization
标题、
Content-Type
Content-Length
之类的东西,以及主体(在本例中)是
multipart/related

所以我既没有得到优雅的

resolve
消息回复,也没有得到有用的
reject
结果,而只是
TypeError: Failed to fetch

如果我仅依靠拒绝,我不会知道这实际上是 400。只有网络工具揭示了这一点。 有人知道为什么这个 400 错误会被“吞没”吗?我需要做什么才能捕获它?

其他编辑

回复评论的更多细节。获取的代码

周围

看起来像这样: async send() { this._build(); return await fetch(this._parameterizedUrl, this._options); }

它包含在一个对象中,该对象仅封装了创建请求的过程(称为
Request

)。所以

this
指针指的是封装对象。
this._parameterizedUrl
只是已经发布的 URL 字符串的值,
this._options
是已经提到的选项对象。对
build()
的调用只是将
Request
对象的值组装到
options
参数中(但也支持 URL 参数,在本例中未使用)
调用此函数的代码如下所示:

const request = Request.post(uploadUrl); request.setContentType(contentType); request.setBody(body); request.setAccessToken(accessToken); request.addHeader('Content-Length', contentLength); const response = await request.send();

Request.post(uploadUrl)

调用是创建我的

Request
对象的简写(这是我自己的封装,如上所述)
此调用将抛出一个错误,该错误在堆栈中较早的位置被捕获。 

Failed to fetch

错误的跟踪的下一行如下所示:

TypeError: Failed to fetch
    at Request.send (api.js:240:1)

完整再现

document.addEventListener('DOMContentLoaded', async () => { const url = 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart'; const options = {}; const authToken = '<Add Auth Token>'; const boundary = 'boundary-' + Math.random().toString(36).substring(2); const contentType = `multipart/related; boundary=${boundary}`; // Body part meta data for the filename const meta = { name: 'test.json' }; // Body part for media (the file) const data = { foo: "bar", bar: "baz" } const metaBlob = new Blob([JSON.stringify(meta)], { type: 'application/json', }); const mediaBlob = new Blob([JSON.stringify(data)], { type: 'application/json', }); const body = new FormData(); body.append('metadata', metaBlob, "metadata"); body.append('media', mediaBlob, name); let contentLength = metaBlob.size + mediaBlob.size; const headers = new Headers(); headers.append('Authorization', `Bearer ${authToken}`); headers.append('Content-Type', contentType); headers.append('Content-Length', contentLength); options['method'] = 'POST'; options['headers'] = headers; options['body'] = body; try { const response = await fetch(url, options); console.log(response); } catch (err) { console.error(err); } });

	
javascript google-drive-api fetch-api
1个回答
0
投票

修改后的脚本:

<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Google Drive Test</title> <script> document.addEventListener('DOMContentLoaded', async () => { const url = 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart'; const options = {}; const authToken = '<Add Auth Token>'; // Body part meta data for the filename const meta = { name: 'test.json' }; // Body part for media (the file) const data = { foo: "bar", bar: "baz" } const metaBlob = new Blob([JSON.stringify(meta)], { type: 'application/json', }); const mediaBlob = new Blob([JSON.stringify(data)], { type: 'application/json', }); const body = new FormData(); body.append('metadata', metaBlob, "metadata"); body.append('media', mediaBlob, name); const headers = new Headers(); headers.append('Authorization', `Bearer ${authToken}`); options['method'] = 'POST'; options['headers'] = headers; options['body'] = body; try { const response = await fetch(url, options); const res = await response.json(); console.log(res); } catch (err) { console.error(err); } }); </script> </head> <body></body> </html>

运行此脚本,得到以下结果。

{ "kind":"drive#file", "id":"###", "name":"test.json", "mimeType":"application/json" }

	
© www.soinside.com 2019 - 2024. All rights reserved.