JavaScript 的 Fetch 方法可以在大部分场景取代传统的 XMLHttpRequest 请求,或者 jQuery 的 $.ajax 方法。但是 Fetch 如何进行错误处理呢?
对于严重的错误,Fetch 会报错,因为这次请求是失败的,比如请求不存在的网址,或者因为跨域被禁止的网址,或者网络超时,这时候根本无法和服务器建立连接。这时 catch 会捕捉到错误信息:
fetch('https://ssss/')
.then(res=>res.text())
.then(data=>console.log(data))
.catch(err=>console.log(err))
要理解上面代码的执行以及 Fetch 的错误处理机制,就需要了解 Promise 对象。Fetch 运行时会建立一个 Promise 对象,根据运行结果,这个对象可能进入成功状态(resolved),继续执行第二行的代码;也可能进入失败状态(reject),则执行 catch 。
但遇到 403、404、500 之类异常状态码,catch 却没有捕捉到错误。如下:
fetch('https://saber.love/f/')
.then(res=>res.text())
.then(data=>console.log(data))
.catch(err=>console.log(err))
虽然浏览器报错了 403,但是代码依旧输出了返回的结果,没有触发 catch 里的错误。这是因为这次请求成功和服务器建立了连接,Fetch 的结果是成功的(resolved),所以就照常进入了第二行代码(then)。我们可以在这里面手动分析一下错误,然后手动返回一个失败(reject)状态的 Promise 对象,使代码接下来进入 catch 执行。
fetch('https://saber.love/f/')
.then(res=>{
console.log(res);
if (res.ok) {
return res.text();
}else{
return Promise.reject(res.status);
}
})
.then(data=>console.log(data))
.catch(err=>console.log('状态码:'+err))
第二步我打印了 Fetch 返回的 Response 对象,可以用里面的 ok 属性来判断请求是否出现了问题,或者自己根据状态码判断。如果出现了问题,手动创建一个失败的 Promise 对象,进入 catch 处理错误。
补充知识:
fetch('https://cdn.jsdelivr.net/npm/@trigrou/[email protected]/WebContent/zip.js')
.then(console.log(11))
.then(console.log(22))
.then(console.log(33))
一个 promise 成功后可以触发后面的多个 then,以前我以为必须每一个 then 里再返回一个 promise 对象才能继续执行下一个 then。结果发现不用。
catch 前面有多个 then 的话,可以捕获所有的 then 的异常处理,不需要和 then 一一配对。
Google Chrome 71
Mac OS X 10.13.6
"一个 promise 成功后可以触发后面的多个 then,以前我以为必须每一个 then 里再返回一个 promise 对象才能继续执行下一个 then。结果发现不用。"
返回的值相当于Promise.resolve(returnValue)了