为了方便讲解,我们先来复习一下错误处理的必须武器 try catch,如果你已经很熟了可以跳过这一段:

try/catch/finally

try /catch/finally属于流程控制的逻辑区块 (跟if/else一样),以下分别介绍:

openFile();
try {
  writeFile(theData); // 可能产生例外
} catch(e) {
  handleError(e); // 处理可能发生的例外
} finally {
  closeFile(); // 总是在 try 结束后关闭档案
}
  • try

此区块是主要的approve程式执行区块,只要在这个区块的任何一后端是什么工作行抛出错误 (无论有没有用到throw),就json数据不会继续往后端开发是干什么的下执行,而是跳到 catch 区块第一行开始执行。

  • catch

此区块可以在错误发生时,自动捕捉进来这个区块,会进来代表「出代志」了,通常会针对错误做一些jsonobject对症下药或善后处理,起码可以确保程式不会直接死当。

  • - finally

此区块是无论如何都会执行到的,try或 catch 区块执json格式行完就会进来,用来处理一些无论有没有错误都apple要做的事情 (比如把 loading 关掉、写 log 等)。

错误的种类

来谈谈错误的种类,了解一下appstore「错误」到底是什么?才会知道该怎么处理它:

程式开发者的错误 (json怎么读programmer errors):

即程式本身的 bug,错误是程式本身没写对造成的。常见的例如:

  • 语法approach错误 (sappearanceyntax error):少括号、关键字approve拼错等
  • 取值错误 (reference error):变数、函式忘记宣告就使用
  • 类型错误 (type error):在 Number 类型的变数使用 Object 的函式

这类型的错误代表与开发者的意图背道而驰,因此没有悬念,就是一定要把它改对,通常透过开发后端需要学什么人员工具可以轻松找appearance到原因。

运算的错误 (ope前端开发需要学什么rational errors)

在程式本身没有 bug 的情况下,错误json是什么意思发生在系统本身,通常是程式与外部互动前端下发生,外部可能是使用者、网路远端、档案系统。常见的例如:

  • 使用后端是做什么的者输入极端值
  • 网路连线问题
  • 记忆体超出负荷

这类型的错误代表,通常在使用者「预想」情况下,程后端开发是干什么的式是可以正常运作的,但是如果:

十笔资料可以跑,那十万笔呢?
都市可以跑,那偏乡地区呢?
json 档案可以处理,那 xml 呢?

因此,其实这类型的错误不太算是「错误」,毕竟部分的 case 都还是可以运作的,或许比较适合称呼为例外(exception)。

这类型的错误处理起来前端工程师就复杂许多,需要对症下药,

  • initial:针对首次使用服务可能会没有初始值的问题,可以视情况先做 initial 动作。
let file;
try {
    file = readFile(filePath);
} catch (err){
    file = createFile(filePath);
}
console.log(file);
  • retry:针对网路连线类型的问题,可以限制次数 retry。
let retryCount = 0;
const retryMax = 3;
do {
    try {
        console.log(retryCount);
        // ...
        // 可能失败的 code 放这 
        // ...
        break;
    } catch (err){
        console.log(err);
        retryCount++;
        if (retryCount >= retryMax) {
            // 超过 retry 次数强制跳出
            break;
        } else {
            // 还没超过可以再试一次
            continue;
        }
    }
} while (true);
  • unknown:面对未知的问题,都应该要有最后一道防线,发生例外时记下 Log,跳出 toast 讯息提醒前端,并关掉 loading 让使用者仍然可以进行其他操作等。
setLoading(true);
try {
    // ...
    // 可能失败的 code 放这 
    // ...
} catch (err){
    logToDB(err);
} finally {
    setLoading(false);
    toast('系统不稳,请稍后再试');
}

我可以用 if/else 来处后端开发是干什么的理错误吗?

未知的问题在catch处理很合理,appearance有一些已知的问题也放后端catch处理,但既然我都知道这边有可能会出问题了,为何不干脆用 if/else 判断处理?

这个问题其实我也觉得稍微模糊,我的想法是appointment,需要先去定义出,catch究竟要接收什么?是所有取不回资料的状况吗?还是针对非正常流程的处理?针对不同的目的,应该使用不同的处理,以下是我的一些想法

适合放在catch处理的:

  • I/O 时发生错误,比如:读写前端学什么档案、fetch资料途中,发生例外appear情况
  • 无法完成预期的工作,比如:想要读取登入后的画面,但因为还没登前端面试题入导致的错误
  • 内部错误,比如后端自己死掉,或是前端传送错误参数

不适合放在catch处理的(可以用 if/else 处理):

  • 查不到资料 (而非查资料失败) 的情况,比如:资料库查询,query 不到东西的情况下,需要处理空值,后端开发工程师而非抛出错误。
  • 询问类,比如:手机要读取联络人清单的权限,当回传的结果是false,也就是使用者不授予权限时。

但这也不是硬性规定,单纯是不同json格式的想法导json怎么读致不同的设计,甚至不同的 API 在处理错误的状态也都不尽相同,因此笔者认为,只要整个 app 在面对错误是一致就可以了(比如查无资料要嘛都放else,要嘛都放catch)。

为什么错误处理是最容易被忽略的一前端面试题

回归到开头的问题,为什么错误处理appreciate往往是最容易被忽略的一块?

  1. 相对陌生
    网路上的教学影approve片,实体课程里面的教材,甚前端和后端的区别至 StackOverflow 等技术讨论论坛,绝大多数的篇幅也都是在教如何「application写出你想要的后端框架 feature」,而非「修补可能发生的 exception」。
  2. 黑天鹅
    解决问题的第一步,是发现并重现问题,这样修好了才知道自己不是蒙到。但很多错误是在特定环境才会发生,后端比如直appearance接操作 A 没事,但先操作 B 再json解析操作 A 就会错误。甚至要是极端情况 (极短时间、大量资料) 才发生,因此光是「产生」这种例外就很困难了。
  3. 看不见的防护网
    就算真的把这些难后端开发是干什么的缠的问题搞定了,成果也很难被看见,因为对前端开发需要掌握什么技术于使用者 / PM 来说,发生错误令人烦躁,但没发生错误却像是基本,也许只有 20% 的时间会发生错误,但我们却需要花费 80% 的时间去处理。

类比来说,其实错误处理很像是现实社会中的「保险」:

  1. 相对陌生
    许多人常常「主动」去自学股票、网页、厨json文件是干什么的艺等学问,而保险也是一门学问,但有趣的是,大部分接后端工程师触到保险的人属于「被动」接触,也就是迫于需要,不得后端开发不去理解,往往是生活中出现漏洞才会想到。
  2. 黑天鹅
    大家都知道保险重要,因为永远不知道明天跟意外哪个先到,尤其意外愈严重愈重要,但严重的意外本来就很少见,当我们意识到时,往往已经深陷泥沼。
  3. 看不见的防护网
    即便我们approve真的把保险买齐了,医疗意外储蓄一应俱全,甚至连长照险后端开发需要学什么都超前部署,生活品质短时间仍然不会有变化,毕竟保险确保的是,即便意外发生,仍然确保你有一定的生活品质。

当然啦,错误处理跟保险还是有很多细节前端学什么、情境的不同,不可完全类比,这边只是笔者有感而发 XD,觉得有些事情,我们在写程式的时候会碰到,前端工程师在现实生活中也会碰到。

结语

学好Erroapprover Handling ,给自己code加一份保险吧~下课啰。

预告….(被打),下期讲「未知与空json是什么意思值 undefined、null、NaN」