发送请求, 请写好Try catch

764 阅读1分钟

日常搬砖的时候一定会需要发送请求,发送请求就必须要考虑到出错的情况。及时报错并且附上尽可能详细的信息,一定会方便自己及时解决问题。

如何写好一个try catch 就尤为重要。

为一个请求包上try catch

try{
    const response = fetch(url, init)
}catch(err){
// console.log(err);
}

这就是一个简单的try catch .

那什么时候会报错呢? 答案是: 出现跨域等情况的时候。这时候根本没有response, fetch 率先抛出了错误。

但是,如果这个fetch返回了response,这个时候是不会报错的。因为try catch并不去检查 response是否ok.

(关于什么时候是ok的,看这Response.ok - Web APIs | MDN (mozilla.org)

对于前端来说,api返回的所有状态并不都是成功的,非200的状态都代表的后端出现了某种问题。

所以在response的状态不ok的时候,应该抛出一个错误。 为了更好地记录下错误信息,我们可以在基于Error,另起一个新的类,用于记录和传递error

Error 类型看这里Error - JavaScript | MDN (mozilla.org)

class HttpRequestError extends Error {
    public readonly name: string = 'HttpRequestError';
    public readonly url?: string;
    public readonly response?: Response;
    public constructor(init: HttpRequestErrorInit, options?: ErrorOptions) {
        super(init.message ?? 'Http request failed.', options);
        this.url = (init.url && String(init.url)) ?? init.response?.url;
        this.response = init.response;
    }
}

try{
    const response = fetch(url, init)
    if(!response.ok){
        throw new HttpRequestError({
        message: `Http request failed with status code ${response.status}`,
        response,
        url,
    });
    }
}catch(err){
       throw err;
}

为一群请求包上try catch

很多时候,一次请求并不能完成整个业务逻辑。 需要有几个请求串行起来才能完成一个完整的业务操作。这其中每一次操作都有让整个操作失败的风险。

我们可以在组合操作分最外部包上try catch, 以此接收出现的错误。

给一个特例进行松绑

为了方便,我们会把fetch的操作进行一个包装,以此复用代码,增加效率和可读性。但是总有那么一两个api,需要我们包容404或者其他的情况,这时候,为了不让报错中断整个业务链路的执行,我们可以在某个特定的请求中包裹一个try catch, 在特殊的情况中,把一些状况忽略掉。

下面的例子就展示了,当接口返回404时,我们正常的返回一个设计好的值。并且终止当前的操作。

function _fetch(url, init){
    try{
        const response = fetch(url, init)
        if(!response.ok){
            throw new HttpRequestError({
            message: `Http request failed with status code ${response.status}`,
            response,
            url,
        });
        }
    }catch(err){
        throw err;
    }
}

function getSomeInfo(props){
try{
    const response = _fetch(url, props)

}catch(err){
    if(err instanceof HttpRequestError){
        if (err.response?.status ===404){
            // do something
            return {}
        }
    }else{
        throw err;
    }
}
}