我编写了一个函数来使用fetch捕获非 200 个结果:
1 function $get(url, callback) {
2 fetch(url, {credentials: "same-origin"})
3 .then(resp => {
4 if (!resp.ok) {
5 resp.text().then((mesg) => {
6 throw {"stat": resp.status, "mesg": mesg.trim()}
7 })
8 return resp.text()
9 }
10 return resp.json()
11 })
12 .then(data => callback({"stat": 200, "data": data}))
13 .catch(error => callback(error))
14}
我在第 9 行出错:
ERROR: TypeError: Failed to execute 'text' on 'Response': body stream already read
我必须编写第 5~7 行所示代码的原因是,如果我写:
if (!resp.ok) {
throw {"stat": resp.status, "mesg": resp.statusText}
return resp.json()
我会收到类似的错误消息{"stat": 403, "mesg": "Forbidden"}
,而我想要的是:{"stat": 403, "mesg": "invalid user name or password"}
。
在服务器端,我的 go 程序将生成非 200 回复,如下所示:
> GET /api/login?u=asdf&p=asdf HTTP/1.1
> Host: localhost:7887
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 403 Forbidden
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Sat, 17 Jul 2021 11:53:16 GMT
< Content-Length: 25
<
invalid username or password
即 go 库不修改 http 状态文本,而是将错误消息放在body 中,这可能是 http 标准规定的(例如,状态文本不能更改)。
所以,我的问题是,要么:
=== 编辑 ===
以下代码可以正常工作,但是,正如注释所指出的那样,它似乎使用了“反”模式:
function $get(url, callback) {
fetch(url, {credentials: "same-origin"})
.then(resp => {
if (!resp.ok) {
resp.text().then((mesg) => {
callback({"stat": resp.status, "mesg": mesg.trim()})
})
return new Promise(function(_, _) {})
}
return resp.json()
})
.then(data => callback({"stat": 200, "data": data}))
.catch(error => { console.log(`GET ${url}\nERROR: ${error}`) })
}
然而,这母鹿不工作:
function $get(url, callback) {
fetch(url, {credentials: "same-origin"})
.then(resp => {
if (!resp.ok) {
resp.text().then((mesg) => {
throw `{"stat": resp.status, "mesg": mesg.trim()}`
})
}
return resp.json()
})
.then(data => callback({"stat": 200, "data": data}))
.catch(error => { console.log(`GET ${url}\nERROR: ${error}`) })
}
该throw
会产生这个错误,而不是把控制权交给catch
下面:
127.0.0.1/:1 Uncaught (in promise) {"stat": resp.status, "mesg": mesg.trim()}
考虑到您正在使用,fetch
您还可以使用async/await
并执行以下操作。:
async function $get(url, callback) {
try {
const resp = await fetch(url, {credentials: "same-origin"});
if (!resp.ok) {
// this will end up in the catch statement below
throw({ stat: resp.status, mesg: (await resp.text()).trim());
}
callback({ stat: 200, data: await resp.json() });
} catch(error) {
callback(error);
}
}
我不明白你为什么要使用callback
函数 :) 那些都是 1999
为了解释您的错误,您resp.text()
在出现错误时调用了两次。为了防止这种情况,您应该立即返回从第一次resp.text()
调用链接的承诺。这也会抛出错误并在没有到达连续then()
语句的情况下在 catch 块中结束:
function $get(url, callback) {
fetch(url, {credentials: "same-origin"})
.then(resp => {
if (!resp.ok) {
return resp.text().then((mesg) => {
// ^^^^^^
throw {stat: resp.status, error: mesg.trim()}
});
}
return resp.json() ;
})
.then(data => callback({stat: 200, data }))
.catch(error => callback(error))
}
$get
不使用回调的“正确”函数:
function $get(url) {
return fetch(url, {credentials: "same-origin"}).then(async (resp) => {
const stat = resp.status;
if (!resp.ok) {
throw({ stat, error: (await resp.text()).trim() });
}
return { stat, data: await resp.json() };
});
}
您可以像这样消费:
$get('https://example.com')
.then(({ stat, data }) => {
})
.catch({ stat, error}) => {
})
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句