高质量Node.js微服务的编写和部署

  1.2 ES2015 Promise

  所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。

物联网

  一个 Promise 一般有3种状态:

  1.pending : 初始状态, 不是 fulfilled ,也不是 rejected .

  2.fulfilled : 操作成功完成.

  3.rejected : 操作失败.

  一个 Promise 的生命周期如下图:

物联网

  下面我们看一段具体代码:

物联网

  asyncFunction 这个函数会返回 Promise 对象, 对于这个 Promise 对象,我们调用它的 then 方法来设置 resolve 后的回调函数, catch 方法来设置发生错误时的回调函数。

  该 Promise 对象会在 setTimeout 之后的 16ms 时被 resolve , 这时 then 的回调函数会被调用,并输出’Async Hello world’ 。

  在这种情况下 catch 的回调函数并不会被执行(因为 Promise 返回了 resolve), 不过如果运行环境没有提供 setTimeout 函数的话,那么上面代码在执行中就会产生异常,在 catch 中设置的回调函数就会被执行。

物联网

  小结

  如果是编写一个 SDK 或 API,推荐使用传统的 callback 或者 Promise,不使用 generator 的原因是:

  generator 的出现不是为了解决异步问题

  使用 generator 是会传染的,当你尝试 yield 一下的时候,它要求你也必须在一个 generator function 内

  看来学习 Promise 是水到渠成的事情。

  2. Express、Koa 的异常处理

物联网

  一个友好的错误处理机制应该满足三个条件:

  对于引发异常的用户,返回 500 页面

  其他用户不受影响,可以正常访问

  不影响整个进程的正常运行

  下面我们就以这三个条件为原则,具体介绍下 Express、Koa 中的异常处理。

  2.1 Express 异常处理

  在 Express 中有一个内置的错误处理中间件,这个中间件会处理任何遇到的错误。

  如果你在 Express 中传递了一个错误给 next() ,而没有自己定义的错误处理函数处理这个错误,这个错误就会被 Express 默认的错误处理函数捕获并处理,而且会把错误的堆栈信息返回到客户端,这样的错误处理是非常不友好的。

  还好我没可以通过设置 NODE_ENV 环境变量为 production ,这样 Express 就会在生产环境模式下运行应用,生产环境模式下 Express 不会把错误的堆栈信息返回到客户端。

  在 Express 项目中可以定义一个错误处理的中间件用来替换 Express 默认的错误处理函数:

物联网

  在所有其他 app.use() 以及路由之后引入以上代码,可以满足以上三个友好错误处理条件,是一种非常友好的错误处理机制。

  2.2 Koa 异常处理

  我们以 Koa 1.x 为例,看代码:

物联网

  把上面的代码放在所有 app.use() 函数前面,这样基本上所有的同步错误均会被try{} catch(err){} 捕获到了,具体原理大家可以了解下 Koa 中间件的机制。

  2.3 未捕获的异常 uncaughtException

  上面的两种异常处理方法,只能捕获同步错误,而异步代码产生的错误才是致命的, uncaughtException 错误会导致当前的所有用户连接都被中断,甚至不能返回一个正常的 HTTP 错误码,用户只能等到浏览器超时才能看到一个 no data received 错误。

  这是一种非常野蛮粗暴的异常处理机制,任何线上服务都不应该因为 uncaughtException 导致服务器崩溃。