{"action":"created","issue":{"url":"https://api.github.com/repos/feross/standard/issues/298","labels_url":"https://api.github.com/repos/feross/standard/issues/298/labels{/name}","comments_url":"https://api.github.com/repos/feross/standard/issues/298/comments","events_url":"https://api.github.com/repos/feross/standard/issues/298/events","html_url":"https://github.com/feross/standard/issues/298","id":112305426,"number":298,"title":"New rule: callback-return","user":{"login":"LinusU","id":189580,"avatar_url":"https://avatars.githubusercontent.com/u/189580?v=3","gravatar_id":"","url":"https://api.github.com/users/LinusU","html_url":"https://github.com/LinusU","followers_url":"https://api.github.com/users/LinusU/followers","following_url":"https://api.github.com/users/LinusU/following{/other_user}","gists_url":"https://api.github.com/users/LinusU/gists{/gist_id}","starred_url":"https://api.github.com/users/LinusU/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LinusU/subscriptions","organizations_url":"https://api.github.com/users/LinusU/orgs","repos_url":"https://api.github.com/users/LinusU/repos","events_url":"https://api.github.com/users/LinusU/events{/privacy}","received_events_url":"https://api.github.com/users/LinusU/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/feross/standard/labels/feature%20request","name":"feature request","color":"207de5"},{"url":"https://api.github.com/repos/feross/standard/labels/v6","name":"v6","color":"5319e7"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":11,"created_at":"2015-10-20T07:39:11Z","updated_at":"2015-12-25T16:51:51Z","closed_at":null,"body":"Suggesting that we include the rule [callback-return](http://eslint.org/docs/rules/callback-return.html)\r\n\r\nCurrently all but one of our repos passes this test.\r\n\r\n```text\r\nstandard: Use JavaScript Standard Style (https://github.com/feross/standard) \r\n  standard/tmp/fastfall/bench.js:48:3: Expected return with your callback function. (callback-return)\r\n  standard/tmp/fastfall/bench.js:49:3: Expected return with your callback function. (callback-return)\r\n  standard/tmp/fastfall/bench.js:50:3: Expected return with your callback function. (callback-return)\r\n  standard/tmp/fastfall/example.js:18:5: Expected indentation of 2 space characters but found 4. (indent)\r\n  standard/tmp/fastfall/example.js:19:3: Expected indentation of 0 space characters but found 2. (indent)\r\nnot ok 88 fastfall\r\n```\r\n\r\nI have looked at the code and it's an easy fix, I could submit a pull request over there.\r\n\r\n-----\r\n\r\n# Enforce Return After Callback (callback-return)\r\n\r\nThe callback pattern is at the heart of most I/O and event-driven programming\r\n in JavaScript.\r\n\r\n```js\r\nfunction doSomething(err, callback) {\r\n    if (err) {\r\n        return callback(err);\r\n    }\r\n    callback();\r\n}\r\n```\r\n\r\nTo prevent calling the callback multiple times it is important to `return` anytime the callback is triggered outside\r\n of the main function body. Neglecting this technique often leads to issues where you do something more than once.\r\n For example, in the case of an HTTP request, you may try to send HTTP headers more than once leading node.js to `throw`\r\n a `Can't render headers after they are sent to the client.` error.\r\n\r\n## Rule Details\r\n\r\nThis rule is aimed at ensuring that callbacks used outside of the main function block are always part-of or immediately\r\npreceding a `return` statement. This rules decides what is a callback based on the name of the function being called.\r\nBy default the rule treats `cb`, `callback`, and `next` as callbacks.\r\n\r\nThe following patterns are considered problems:\r\n\r\n```js\r\n/*eslint callback-return: 2*/\r\n\r\nfunction foo() {\r\n    if (err) {\r\n        callback(err); /*error Expected return with your callback function.*/\r\n    }\r\n    callback();\r\n}\r\n```\r\n\r\nThe following patterns are not considered problems:\r\n\r\n```js\r\n/*eslint callback-return: 2*/\r\n\r\nfunction foo() {\r\n    if (err) {\r\n        return callback(err);\r\n    }\r\n    callback();\r\n}\r\n```\r\n\r\n### Options\r\n\r\nThe rule takes a single option, which is an array of possible callback names.\r\n\r\n```json\r\ncallback-return: [2, [\"callback\", \"cb\", \"next\"]]\r\n```\r\n\r\n### Gotchas\r\n\r\nThere are several cases of bad behavior that this rule will not catch and even a few cases where\r\nthe rule will warn even though you are handling your callbacks correctly. Most of these issues arise\r\nin areas where it is difficult to understand the meaning of the code through static analysis.\r\n\r\n#### Passing the Callback by Reference\r\n\r\nHere is a case where we pass the callback to the `setTimeout` function. Our rule does not detect this pattern, but\r\nit is likely a mistake.\r\n\r\n```js\r\n/*eslint callback-return: 2*/\r\n\r\nfunction foo(callback) {\r\n    if (err) {\r\n        setTimeout(callback, 0); // this is bad, but WILL NOT warn\r\n    }\r\n    callback();\r\n}\r\n```\r\n\r\n#### Triggering the Callback within a Nested Function\r\n\r\nIf you are calling the callback from within a nested function or an immediately invoked\r\nfunction expression, we won't be able to detect that you're calling the callback and so\r\nwe won't warn.\r\n\r\n```js\r\n/*eslint callback-return: 2*/\r\n\r\nfunction foo(callback) {\r\n    if (err) {\r\n        process.nextTick(function() {\r\n            return callback(); // this is bad, but WILL NOT warn\r\n        });\r\n    }\r\n    callback();\r\n}\r\n```\r\n\r\n#### If/Else Statements\r\n\r\nHere is a case where you're doing the right thing in making sure to only `callback()` once, but because of the\r\ndifficulty in determining what you're doing, this rule does not allow for this pattern.\r\n\r\n```js\r\n/*eslint callback-return: 2*/\r\n\r\nfunction foo(callback) {\r\n    if (err) {\r\n        callback(err); // this is fine, but WILL warn /*error Expected return with your callback function.*/\r\n    } else {\r\n        callback();    // this is fine, but WILL warn /*error Expected return with your callback function.*/\r\n    }\r\n}\r\n```\r\n\r\n## When Not To Use It\r\n\r\nThere are some cases where you might want to call a callback function more than once. In those cases this rule\r\n may lead to incorrect behavior. In those cases you may want to reserve a special name for those callbacks and\r\n not include that in the list of callbacks that trigger warnings.\r\n\r\n\r\n## Further Reading\r\n\r\n* [The Art Of Node: Callbacks](https://github.com/maxogden/art-of-node#callbacks)\r\n* [Nodejitsu: What are the error conventions?](http://docs.nodejitsu.com/articles/errors/what-are-the-error-conventions)\r\n\r\n## Related Rules\r\n\r\n* [handle-callback-err](handle-callback-err.md)\r\n\r\n-----\r\n\r\n*I found the rule while comparing which rules `xo` has versus `standard` here: https://github.com/feross/standard/issues/216#issuecomment-127569835*"},"comment":{"url":"https://api.github.com/repos/feross/standard/issues/comments/167250164","html_url":"https://github.com/feross/standard/issues/298#issuecomment-167250164","issue_url":"https://api.github.com/repos/feross/standard/issues/298","id":167250164,"user":{"login":"mcollina","id":52195,"avatar_url":"https://avatars.githubusercontent.com/u/52195?v=3","gravatar_id":"","url":"https://api.github.com/users/mcollina","html_url":"https://github.com/mcollina","followers_url":"https://api.github.com/users/mcollina/followers","following_url":"https://api.github.com/users/mcollina/following{/other_user}","gists_url":"https://api.github.com/users/mcollina/gists{/gist_id}","starred_url":"https://api.github.com/users/mcollina/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mcollina/subscriptions","organizations_url":"https://api.github.com/users/mcollina/orgs","repos_url":"https://api.github.com/users/mcollina/repos","events_url":"https://api.github.com/users/mcollina/events{/privacy}","received_events_url":"https://api.github.com/users/mcollina/received_events","type":"User","site_admin":false},"created_at":"2015-12-25T16:51:51Z","updated_at":"2015-12-25T16:51:51Z","body":"I agree.\nIl giorno ven 25 dic 2015 alle 13:15 Feross Aboukhadijeh <\nnotifications@github.com> ha scritto:\n\n> Just ran the tests with eslint 1.10.3 and this rule:\n>\n> [2, [\"cb\", \"callback\", \"next\", \"done\"]]\n>\n> All tests pass. This rule finally looks mature enough to use. Out of an\n> abundance of caution, let's add it in v6.\n>\n> —\n> Reply to this email directly or view it on GitHub\n> <https://github.com/feross/standard/issues/298#issuecomment-167225975>.\n>\n"}}