本文由云+社区宣布
绝大多数顺序只斟酌了接口一般事情的场景,而用户在运用我们的产物时碰到的种种异常,全都丢在看似 ok 的 try catch 中。假如没有做好异常的兼容和兜底处置惩罚,会极大的影响用户体验,严峻的还会带来平安和资损风险。
接口异常,一般能够分为以下三类:
- CGI 逻辑失足。如挪用方入参缺失类营业逻辑报错;
- 效劳不稳定。如效劳器不稳定致使 nginx 种种 500、502,cgi 途径调解致使的 404
- 用户收集环境差。如,收集不稳定、网速慢、运营商挟制等
那末,我们在写代码时,怎样疾速的模仿这些接口异常,做好顺序的兼容处置惩罚呢?
本日向人人引见收集调试神器 whistle 的收集异常调试要领,假如你还没用过 whistle,请参考《8102 年的顺序员不需要 Hosts 和 Fiddler》。
假定我们有以下前端页面 index.html,安排在本身的当地途径:
<p id="success" style="color:green;"></p>
<p id="fail" style="color:red;"></p>
<script>
fetch(`/mock?r=${Math.random()}`)
.then(response => {
return response.json()
})
.then(v => {
document.getElementById('success').innerHTML = v.data;
}).catch(err => {
document.getElementById('fail').innerHTML = err.message;
})
</script>
接下来,翻开 whistle Rules 设置面板 http://127.0.0.1:8899/#rules ,设置模仿的 demo page 和 mock CGI:
*/mock file://({"code":0,"data":"success"}) # 设置 mock cgi 为模仿的 json 数据
example.com file:///Users/kaiye/Projects/Markdown/20181213/ # 设置恣意域名到当地 demo 目次,这里注重替换成本身的途径
翻开 http://example.com ,一般逻辑下页面展现出了绿色的 success ,如今我们最先到场一些收集异常。
1、营业逻辑异常处置惩罚
比方 CGI 没有返回 data
字段,而是返回了一个毛病码 code
和对应的 message
,针对这类营业逻辑异常我们只需在第二个 then
中做好 code 值的推断即可(注重,这里的 code、message、data 只是示例,现实营业 CGI 中的 JSON 构造体的字段名极能够差别):
fetch(`/mock?r=${Math.random()}`)
.then(response => response.json())
.then((v) => {
// 营业逻辑异常处置惩罚
if (v.code !== 0) {
return Promise.reject(new Error(`ERROR_LOGIC_CODE:${v.code}`));
}
document.getElementById('success').innerHTML = v.data;
})
.catch((err) => {
document.getElementById('fail').innerHTML = err.message;
});
响应的 whistle 设置以下:
*/mock file://({"code":12345,"message":"some_logic_error"}) # 模仿营业逻辑异常
2、效劳器异常处置惩罚
假如效劳器直接抛出了 502 毛病码,我们愿望代码能给用户提醒的同时,再做一个异常上报。
fetch(`/mock?r=${Math.random()}`)
.then((response) => {
// 效劳器异常处置惩罚
if (response.ok) {
return response.json();
}
return Promise.reject(new Error(`ERROR_STATUS_CODE:${response.status}`));
})
.then((v) => {
// 营业逻辑异常处置惩罚
if (v.code !== 0) {
return Promise.reject(new Error(`ERROR_LOGIC_CODE:${v.code}`));
}
document.getElementById('success').innerHTML = v.data;
})
.catch((err) => {
const [type, value] = err.message.split(':');
// 异常范例上报
console.log(type, value);
document.getElementById('fail').innerHTML = err.message;
});
经由过程 whistle 的模仿设置以下:
*/mock statusCode://502 # 模仿 HTTP 状况码异常
3、接口被挟制注入
假如 CGI 被运营商挟制注入,能够致使接口返回一个不合法的 JSON 构造,最前面的 response.json()
会抛异常,我们能够提早 catch 住:
fetch(`/mock?r=${Math.random()}`).then((response) => {
// 效劳器异常处置惩罚
if (response.ok) {
return (
response
.json()
// 接口数据解码异常处置惩罚
.catch(err => Promise.reject(new Error('ERROR_DECODE_JSON')))
);
}
return Promise.reject(new Error(`ERROR_STATUS_CODE:${response.status}`));
});
whistle 模仿设置以下:
*/mock file://(<div>hijacking</div>{"code":0,"data":"success"}) # 模仿接口被挟制注入 1
借助 htmlAppend 和 values 设置,能够模仿更庞杂的注入示例:
*/mock file://({"code":0,"data":"success"}) htmlAppend://{hijacking.html} # 模仿接口被挟制注入 2
<script>
alert(‘hijacking’)
</script>
4、用户收集不稳定
假如我们要模仿要求发出 10 秒后断网或收集不通的状况,能够经由过程 whistle 如许设置:
*/mock reqDelay://10000 enable://abort # 模仿 10 秒超时后收集不通
让用户苦苦守候 10 秒,再报错的体验太蹩脚。我们能够封装一个能设置超时时候的要求发送函数,同时把上面提到的毛病异常都一同设置进来。
<p id="success" style="color:green;"></p>
<p id="fail" style="color:red;"></p>
<script>
function myFetch(url, configOptions) {
const options = Object.assign(
{
timeout: 3000
},
configOptions
)
const { timeout } = options
return new Promise((resolve, reject) => {
// 超时异常处置惩罚
const timer = setTimeout(() => {
reject(new Error(`ERROR_TIMEOUT:${timeout}`))
}, timeout)
fetch(url, options)
.then(data => {
clearTimeout(timer)
resolve(data)
})
.catch(err => {
clearTimeout(timer)
reject(err)
})
})
.then(response => {
// 效劳器异常处置惩罚
if (response.ok) {
return (
response
.json()
// 接口数据解码异常处置惩罚
.catch(err => Promise.reject(new Error('ERROR_DECODE_JSON')))
)
} else {
return Promise.reject(
new Error(`ERROR_STATUS_CODE:${response.status}`)
)
}
})
.then(v => {
// 营业逻辑异常处置惩罚
if (v.code !== 0) {
return Promise.reject(new Error(`ERROR_LOGIC_CODE:${v.code}`))
} else {
return v.data
}
})
.catch(err => {
const [type, value] = err.message.split(':')
// 异常范例上报
console.log(type, value)
return Promise.reject(err)
})
}
myFetch(`/mock?r=${Math.random()}`)
.then(data => {
document.getElementById('success').innerHTML = data
})
.catch(err => {
document.getElementById('fail').innerHTML = err.message
})
</script>
如许,自定义的 myFetch
只需关注营业详细逻辑,针对差别的 catch error 做对应的处置惩罚。
除以上提到的协定命令字外,whistle 还支撑 resSpeed 用于模仿低网速传输(单元:kb/s),tpl 协定则能够依据要求传入参数来动态模仿差别的数据。在 Frames 面板,还能够对 WebSocket/Socket 要求举行停息、耽误等收集异常的模仿。
小顺序 fetch API 完成
末了,留一道思考题。
最近微信小顺序开辟异常火,小顺序原生供应的 wx.request API 能用于发送 HTTPS 要求,请在它的基本之上举行封装,支撑 promise 挪用和 timeout
超时时候定义(小顺序默许的要求超时定义在 app.json 中,不够天真),并针对以上提到的 HTTP 状况码异常、接口挟制注入、慢收集、无收集状况等种种收集异常举行兼容处置惩罚。
迎接留言分享你的代码完成
此文已由作者受权腾讯云+社区宣布