木灵鱼儿
阅读:2163
fetch 请求报错处理思路
之前写过一片使用fetch下载文件的方法,但是如果后端返回一个错误对象,使用response.blob()
会将这个错误对象直接转为blob
对象,然后被转为文件下载下来。
但实际上我们是要区分处理的,比如是文件流我们就下载文件,是错误对象,我们就进行错误提示和抛出错误。
所以这里,我主要分享下我对错误处理的思路。
基础知识
首先,在fetch第一个then回调中,我们可以对response
对象进行三种方法操作:
- response.text 返回的是一个纯文本 是一个promise对象
- response.json 返回的是一个对象(json/array) 是一个promise对象
- response.blob 返回一个blob对象,是一个promise对象
三个方法对应后端返回的不同类型,但是需要注意的是response对象只能被上面三种方法中的某一个操作一次;也就是说你text操作了,就不能再json或者blob,否则会报错的。
这就导致,我们没办法直接通过这三个方法进行判断了,比较可惜。
了解这个基本前提,我们还需要知道后端返回的错误对象是什么?
{code: 0,msg: "错误信息",data: null}
一般来说,后端返回的基本都是这种格式,那么我们的重点就是如何区分后端返回的是一个错误对象还是文件流。
区分后端返回的是错误对象还是文件流
这个问题我昨天还在群里问了大佬,大佬给的方案是判断响应头类型。
我试了下,判断头信息是可行的,我这边的项目测试,返回的类型如下:
后端返回错误对象的头类型
application/json; charset=utf-8
后端返回文件流的头类型
text/html; charset=utf-8
不同的项目,返回的类型也是不同的,这个就需要大家自己去看下自己后端返回的是啥类型了。
判断代码
fetch(...省略).then(async response => {
//根据头信息协议判断后端返回的内容
const type = response.headers.get("content-type");
if (type.startsWith("application/json")) {
...后端报错了
//后端报错了
const errorObj = await response.json();
return Promise.reject(errorObj);
}else if (type.startsWith("text/html")) {
//文件流
return response.blob();
}else {
//其他
const err = new Error("下载文件的请求发生错误!");
throw err;
}
}).then(blob => {
//返回blob
...省略
}).catch(err => {
//返回错误
...省略
})
这样我们就可以针对不同的返回内容进行判断,如果不是文件流,我们可以获取到后端返回的错误对象,拿到msg属性,进行错误提示,后端的错误对象就是上面的errorObj
以上就是我对fetch请求错误的处理思路。
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。
相关推荐
Nginx默认不支持带下划线的头信息
前言最近国庆了,由于主要计划被迫放弃,所以只能走点次要计划,就是将个人全栈开发的书签系统移动到其它服务器上,主要还是因为财力问题,无法供给多台服务器,腾讯云也没有什么好活动,全是老用户与狗不得参与系列。无奈的搬运,其中最简单的是项目打包带走,数据库的还原,站点的配置,其中我就遇到了个贼奇葩的问题,就是我的头信息总是获取不到。一开始我是以为是我的反代服务的问题,因为是nodejs的后端服务,如果想要通过域名访问api就不得不通过反代的方式来使用。反代是将a的请求接受后自己再发给真实服务,然后将真实服务的返回再返回给a,其中我们知道一个xhr请求是有很多参数的,其中header头信息也是一种...

Promise失败重试,可指定重试次数
//模拟异步请求 function axiosFn() { return new Promise((resolve, reject) => { const flge = Math.random(); //随机值 setTimeout(() => { //大于0.7就是成功 if (flge > 0.7) { return resolve(flge); } else { return reject(...
animation 动画的三个事件
const div = document.querySelector("div.box"); div.addEventListener("animationstart", function() { //动画开始运行触发 }); div.addEventListener("animationiteration", function() { //动画每执行一次触发一次,适用用多次动画 }); div.addEventListener("animationend", function() { //...
手写Promise
/* * @Author: mulingyuer * @Date: 2021-12-30 22:06:58 * @LastEditTime: 2022-01-03 05:22:30 * @LastEditors: mulingyuer * @Description: 手写promise * @FilePath: \undefinedc:\Users\13219\Desktop\promise.js * 怎么可能会有bug!!! */ /** * @description: 自定义promise * @param {fucntion} executor 执行器函数(同...
深度合并对象的方法
找了很久,现有的库有两个:1. Mergenpm地址: Merge用法:import merge from 'merge'; const obj1 = { name: 2}; const obj2 = { value: 1 }; //合并 merge(obj1,obj2); console.log(obj1); //{name:2,value:1} //克隆合并-与目标对象无关联 const obj3 = merge(true,obj1,obj2); console.log(obj3); //{name:2,value:1} console.log(obj3 === obj1)...
利用JSON过滤对象和数组中指定的key属性
有时候我们在vue中进行for循环,就会涉及到绑定唯一值key的问题,但是并不是任何时候都会存在所谓的唯一值,使用index下标明显是不合适的,官方也不推荐,除非你for循环出来的列表不用变化。所以一般常用的做法就是给for循环的对象添加一个属性,属性的值是随机的uuid或者时间戳。这样前端问题解决了,如果遍历的数据还需要提交到后端,那么不就多了一个属性,这个属性后端不需要的。所以,我们需要在提交数据前,对数据进行过滤。过滤又得for循环删除?那怎么行,有没有那种通用的,简单的方法。过滤方法/** * @description: 过滤对象中指定的属性,也可以拿来浅拷贝 * @para...
Copy 一个复制操作的类
前言js有一个31k多的star的开源复制库:clipboard.js;但是一些简单复制并不想安装一个库来解决,所以就想自己写一个。copy所需要的东西Selection 对象用于获取被用户选中的部分,通过toString()方法可以获取被选中的文本内容,以及js操作选中。MDN文档:SelectionexecCommand 对象用于以命令的形式来操作网页的内容,说白了就是用它来实现复制文本操作,复制的是选中的文本MDN文档:execCommand 需要注意的是,execCommand在未来将会被遗弃,因为这个api本身是从ie浏览器那边继承的,久而久之各大浏览器都对其做了兼容,虽然...
对象扁平化
前言后端返回给前端的数据,有时候会是一个多层级对象,但是我们前端使用的时候,for循环遍历渲染时,多层级对象往往需要进行单独处理,因为还需要判断这个key值是否存在,否则会报错。强行让后端改变数据结构又好像不现实,无奈,只有自己处理了。掘金看到一位大佬文章《【算法】JS 实现对象的扁平化》感觉很合适,逻辑清晰。要求将对象中的层级扁平化,改成如下格式:// 实现一个 flatten 函数,实现如下的转换功能 const obj = { a: 1, b: [1, 2, { c: true }], c: { e: 2, f: 3 }, g: null, }; // 转换为 l...