Skip to content

ktont/horizontal_alert

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 

Repository files navigation

horizontal_alert

任何一段程序的执行都有三种可能,成功、失败和超时。如果只处理了成功,这段程序只能称其为可用。如果处理了失败,那可称其为精良。如果处理了超时,可称无暇

--- 某问,为何要写无瑕的程序?
--- 若问,JavaScript如何写出无暇的程序?

为何要写无瑕的程序。即为自己也为别人,主要还是为了自己。如同做一道饭菜。首先自己要觉得好吃,一是为填饱肚子,二是为了享受美食,对美食色香味的艺术追求。其次让别人也觉得好吃,别人也会欣赏你的美食,从而欣赏你。这样,人人能够看懂并欣赏你的代码。无瑕的代码自己写着舒服,糟糕的代码只会让你跳槽或者沉沦。

JavaScript 如何写出无暇的程序。遵从 JavaScript 三角形原则和六条军规,就可以做到战术上的无瑕。


为了提升语言的品质,JavaScript 社区近年出现的一些技术,甚至还引入了编译器。这些技术中,有些技术表达能力强,灵活。用它们足以写出无暇的程序。

其中有两项技术非常锋利,就是 Promise 和 Generator (Generator又被编译插件简化为async/await)。使用这两项锋利的技术,需要一些手法。如果用不好,会反被其伤。

零、三角形原则

当你写的代码中出现三角形的时候。要注意啦,你的代码开始恶化,开始变质。 出现三角形的原因多种多样,要想抹掉它,没有统一的解法。 此时,需要梳理你的逻辑,调整你的代码。使你的意图和你的代码的表现力到达平衡。 从而抹掉这个三角形。 下面五条军规,能帮助你抹掉大部分的三角形。

什么是三角形代码?例如

mysql.connect(ip, (e, r) => {
  mysql.use(db, (e, r) => {
    mysql.select(sql, (e, r) => {
      mysql.insert(sql, (e, r) => {
        ok
      })
    })
  })
})

一、请直接使用 API 的 Promise

我经常见到下面的代码,它不敢直接使用 API 的 Promise

  return new Promise((resolve, reject) => {
    fetch().then(() => {
      do_something
      do_tomething
      resolve()
    })
  })

正确的做法是

  return fetch()
  .then(do_something)
  .then(do_tomething)

为什么不直接返回 API 的 Promise 呢?原因是他的思想还停留在教科书的例子上,或者停留在回调函数的年代中。 虽然用的是 Promise,但是还是在写回调函数。揉来揉去,弄巧成拙。

用这种错误方式写出的代码,会成为更加恐怖的回调地狱,违反三角形原则。

所以,这样做,是因为三角形原则。

二、 能提前返回就提前返回

  if(success) {
    do_something
  } else {
    do_tomething
  }

不如写成

  if(success) return do_something
  do_tomething

在其他语言中,人们很自然会提前返回,这么做很自然。但是 JavaScript 中不是,人们可能写回调太多,总喜欢把逻辑包起来。提前返回能够抹掉三角形。

所以,这么做,还是因为三角形原则。

三、 大胆的 throw 吧

我常见到这样的代码,当异常时 return {};。 他的想法是,成功的返回一定有值,那么失败的返回就是“空值”。 有这样想法的作者还处在很低的水平上。

如果程序异常,就应放心大胆的 throw。 如果你不知道怎么处理异常,就不要处理他,异常会自然的抛出去。

大胆的 throw 不会让你的程序出现福尔摩斯才能破解的难题。

throw 会让逻辑提前结束,相当于提前返回。

所以,这么做,还是因为三角形原则。

四、 不要使用 Promise.all

很多人会质疑为什么不用 Promise.all。 如果你想并发的执行,那么直接执行Promise就好了。它本身就是异步的,加上await才会变成同步。

Promise.all 违反了三角形原则。 因为 Promise.all 有让代码恶化、类似食物变质一样的因子。 人们慢慢的会把 Promise 代码片段写在 Promise.all 的参数中,代码又变成三角形了。 这是第一个理由。

  • 第二个理由,Promise.all 不会真的变快,因为 JavaScript 是单核的。这个理由很弱,因为太底层了。前端程序员可能更在乎并发的 Ajax。
  • 第三个理由,并发的 Ajax 确实会快。但是不是好的设计。任何程序都不应给它的宿主太大的压力,平滑的运算即有利宿主,也有利用户体验。
  • 第四个理由,Promise.all 的异常可能不是你想要的异常。因为它本身是个 Promise,只能被决定一次。
  • 第五个理由,Promise.all 没有超时,可能永远处于未决定状态。

主要理由是第一个理由。 所以,这么做,还是因为三角形原则。

五、 禁用 try catch

很多人会激烈的反对这条规则。因为他担心实际做不到,所以反对。 我设定这条规则,肯定自己是严格遵守的,没有特别难受。 用 Promise 来写逻辑的话,没有哪种场景是非要用 try catch 不可的。

try catch 本身是一个小三角形,因此它违反了三角形原则,这是第一个理由。

  • 第二个理由,try catch 包不住异步逻辑中的异常,这会给人错觉。
  • 第三个理由,事实证明,很多人懒得去找 bug,会粗暴的把大段代码用 try catch 包起来。
  • 第四个理由,事实再次证明,很多人写 try catch 只是为了把错误秘起来,让代码继续。这种做法,被其他人效法,会像病毒一样蔓延。

Promise 的 catch 完全能胜任捕获异常的任务,并且,就应该用它来捕获异常。 为什么舍近求远呢?

Promise 的 catch 是链式的,而不像 try catch 是三角形的。

所以,这么做,还是因为三角形原则。

六、第六条军规

应该还有第六条军规吧,那就是你自己的发现喽!别忘了告诉我噢。

About

JavaScript三角形原则和六条军规

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published