版本

callback-return

在回调之后要求 return 语句

重要提示

此规则在 ESLint v7.0.0 中已弃用。请使用 eslint-plugin-n 中的相应规则

了解更多

回调模式是 JavaScript 中大多数 I/O 和事件驱动编程的核心。

function doSomething(err, callback) {
    if (err) {
        return callback(err);
    }
    callback();
}

为了防止多次调用回调,重要的是在主函数体外部触发回调时,始终使用 return。忽略此技术通常会导致多次执行某些操作的问题。例如,在 HTTP 请求的情况下,您可能会尝试多次发送 HTTP 标头,从而导致 Node.js 抛出 Can't render headers after they are sent to the client. 错误。

规则详情

此规则旨在确保在主函数块外部使用的回调始终是 return 语句的一部分或紧接在 return 语句之前。此规则根据被调用函数的名称来判断什么是回调。

选项

该规则接受一个选项 - 可能的回调名称数组 - 其中可能包括对象方法。默认的回调名称是 callbackcbnext

默认回调名称

对于此规则,使用默认 ["callback", "cb", "next"] 选项的错误代码示例

在 Playground 中打开
/*eslint callback-return: "error"*/

function foo(err, callback) {
    if (err) {
        callback(err);
    }
    callback();
}

对于此规则,使用默认 ["callback", "cb", "next"] 选项的正确代码示例

在 Playground 中打开
/*eslint callback-return: "error"*/

function foo(err, callback) {
    if (err) {
        return callback(err);
    }
    callback();
}

提供的回调名称

对于此规则,使用 ["done", "send.error", "send.success"] 选项的错误代码示例

在 Playground 中打开
/*eslint callback-return: ["error", ["done", "send.error", "send.success"]]*/

function foo(err, done) {
    if (err) {
        done(err);
    }
    done();
}

function bar(err, send) {
    if (err) {
        send.error(err);
    }
    send.success();
}

对于此规则,使用 ["done", "send.error", "send.success"] 选项的正确代码示例

在 Playground 中打开
/*eslint callback-return: ["error", ["done", "send.error", "send.success"]]*/

function foo(err, done) {
    if (err) {
        return done(err);
    }
    done();
}

function bar(err, send) {
    if (err) {
        return send.error(err);
    }
    send.success();
}

已知限制

由于通过静态分析难以理解程序的含义,因此此规则存在局限性

  • 假阴性,当此规则报告正确的代码时,但程序多次调用回调(这是不正确的行为)
  • 假阳性,当此规则报告不正确的代码时,但程序仅调用回调一次(这是正确的行为)

通过引用传递回调

如果回调是函数的参数(例如,setTimeout),则此规则的静态分析不会检测到程序调用回调。

当此规则报告正确的代码时,假阴性的示例

/*eslint callback-return: "error"*/

function foo(err, callback) {
    if (err) {
        setTimeout(callback, 0); // this is bad, but WILL NOT warn
    }
    callback();
}

在嵌套函数中触发回调

如果程序从嵌套函数或立即调用函数表达式 (IIFE) 中调用回调,则此规则的静态分析不会检测到。

当此规则报告正确的代码时,假阴性的示例

/*eslint callback-return: "error"*/

function foo(err, callback) {
    if (err) {
        process.nextTick(function() {
            return callback(); // this is bad, but WILL NOT warn
        });
    }
    callback();
}

If/else 语句

此规则的静态分析不会检测到程序在 if 语句的每个分支中仅调用回调一次。

当此规则报告不正确的代码时,假阳性的示例

/*eslint callback-return: "error"*/

function foo(err, callback) {
    if (err) {
        callback(err); // this is fine, but WILL warn
    } else {
        callback();    // this is fine, but WILL warn
    }
}

何时不使用

在某些情况下,您可能希望多次调用回调函数。在这些情况下,此规则可能会导致不正确的行为。在这些情况下,您可能希望为这些回调保留一个特殊的名称,并且不将其包含在触发警告的回调列表中。

版本

此规则在 ESLint v1.0.0-rc-1 中引入。

延伸阅读

资源

更改语言