xiaoxiaojx / blog

Project for records problems solved in my work and study.
https://xiaoxiaojx.github.io/
MIT License
253 stars 6 forks source link

Express 错误处理与 Webassembly 编译 #59

Open xiaoxiaojx opened 1 year ago

xiaoxiaojx commented 1 year ago

image

这两个问题没有任何相关性, 碍于篇幅原因就记录在一篇文章中了

Part 1. Express Error Handling

发现一个非常重要的 Express 项目(QPS: 1500 左右)没有错误处理中间件, 意味着已经丢失了大量的运行错误日志, 于是开始亡羊补牢

大部分 Node.js 项目还是基于 Koa, 对于 Express 的中间件写法还是不太熟悉, 查询了一下官方文档的示例

function errorMiddleware(err, req, res, next) {
  console.error(err.stack);
  next(err);
}

看到这里让我比较困惑, 普通的中间件比如 loggerMiddleware 是这样

function loggerMiddleware(req, res, next) {
  console.log("LOGGED");
  next();
}

疑惑的点是 Express 如何区分某个中间件是错误处理中间件还是普通中间件, 因为错误处理中间件传参数是 4 个, 普通中间件是 3 个

app.use(errorHandler);
app.use(myLogger);

于是翻看了一下 Express 的代码实现, 如果一个函数 fn 的 length 属性 !== 4, 那么它 not a standard error handler ?

/**
 * Handle the error for the layer.
 *
 * @param {Error} error
 * @param {Request} req
 * @param {Response} res
 * @param {function} next
 * @api private
 */

Layer.prototype.handle_error = function handle_error(error, req, res, next) {
  var fn = this.handle;

  if (fn.length !== 4) {
    // not a standard error handler
    return next(error);
  }

  try {
    fn(error, req, res, next);
  } catch (err) {
    next(err);
  }
};

好吧, 但愿我不是最后一个知道一个函数的 length 属性即是它参数的个数 ...

errorMiddleware.length;
// 4
loggerMiddleware.length;
// 3

Part 2. Webassembly 编译问题

官方文档 emscriptenCompiling a New C/C++ Module to WebAssembly、知乎这篇 c++项目转成 wasm 全过程 可谓是必读教程。

近期想把一个内部的 C++ SDK 编译为 Wasm, 使用 emmake make -j 编译报了下面的错误, 单独使用 make -j 命令是正常的

error: unknown type name 'u_int64'
error: unknown type name 'u_int8'; did you mean 'u_int'?

一开始感觉以为是 emmake 声明头文件的目录比较特殊, 但当写死了头文件的绝对地址还是找不到类型, 就显得比较诡异

于是写了个最简 demo 发现使用 emmake 时定义了 __unix__ 宏, 却没有定义 __APPLE__

那么为什么在 MacOS 中 emmake 不像 make 一样去定义 __APPLE__ 宏了?

仔细一想当使用 make 编译时是编译出当前平台能运行的二进制文件, 而使用 emmake 则要编译出平台无关的 Wasm 文件, 最后要解释运行在任意平台, 这意味着一个库如果在不同平台有不同的系统调用, 要求它必须兼容 unix 平台, 因为 WIN、APPLE 等平台独有的系统调用 emmake 很难去 Mock 实现, 所以即使是通用的 unix 平台 api 也只能是尽量多的去 Mock