错误优先回调


¥Error-first callbacks

Node.js 核心 API 公开的大多数异步方法都遵循称为错误优先回调的惯用模式。使用这种模式,回调函数作为参数传给方法。当操作完成或出现错误时,回调函数将使用 Error 对象(如果有)作为第一个参数传入。如果没有出现错误,则第一个参数将作为 null 传入。

¥Most asynchronous methods exposed by the Node.js core API follow an idiomatic pattern referred to as an error-first callback. With this pattern, a callback function is passed to the method as an argument. When the operation either completes or an error is raised, the callback function is called with the Error object (if any) passed as the first argument. If no error was raised, the first argument will be passed as null.

const fs = require('node:fs');

function errorFirstCallback(err, data) {
  if (err) {
    console.error('There was an error', err);
    return;
  }
  console.log(data);
}

fs.readFile('/some/file/that/does-not-exist', errorFirstCallback);
fs.readFile('/some/file/that/does-exist', errorFirstCallback); 

JavaScript try…catch 机制无法拦截异步 API 产生的错误。初学者的一个常见错误是尝试在错误优先的回调中使用 throw

¥The JavaScript try…catch mechanism cannot be used to intercept errors generated by asynchronous APIs. A common mistake for beginners is to try to use throw inside an error-first callback:

// THIS WILL NOT WORK:
const fs = require('node:fs');

try {
  fs.readFile('/some/file/that/does-not-exist', (err, data) => {
    // Mistaken assumption: throwing here...
    if (err) {
      throw err;
    }
  });
} catch (err) {
  // This will not catch the throw!
  console.error(err);
} 

这不起作用,因为传给 fs.readFile() 的回调函数是异步调用的。当回调被调用时,周围的代码(包括 try…catch 块)已经退出。在大多数情况下,在回调中抛出错误可能会导致 Node.js 进程崩溃。如果启用了 ,或者已经向 process.on('uncaughtException') 注册了处理程序,则可以拦截此类错误。

¥This will not work because the callback function passed to fs.readFile() is called asynchronously. By the time the callback has been called, the surrounding code, including the try…catch block, will have already exited. Throwing an error inside the callback can crash the Node.js process in most cases. If domains are enabled, or a handler has been registered with process.on('uncaughtException'), such errors can be intercepted.