balderdashy / balderdashy/sails
Throwing exit signals within helpers and actions vs. invoking a callback (`throw 'foo';` vs `return exits.foo();`, and .intercept()
- Dominant language
- JavaScript
- Stars
- 22.8k
- Forks
- 1.9k
- PR merge metrics
- No merged PRs in 30d
Description
**Sails version**: 1.0.0-46
**Node version**: 9.5.0
**NPM version**: 5.6.0
**DB adapter name**: sails-mysql
**DB adapter version**: 1.0.0-17
**Operating system**: macOS High Sierra 10.13.1
Creating a helper that awaits findOne then checking the result is not undefined for some reason causes the controller that called it to produce the error:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
WARNING: Something seems to be wrong with this function.
It is trying to signal that it has finished AGAIN, after
already resolving/rejecting once.
(silently ignoring this...)
To assist you in hunting this down, here is a stack trace:
```
at Object._requestHandler [as get-by-id] (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/machine-as-action/lib/machine-as-action.js:444:16)
at /Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/sails/lib/router/bind.js:247:46
at routeTargetFnWrapper (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/sails/lib/router/bind.js:391:9)
at /Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/sails/lib/router/bind.js:454:14
at Layer.handle [as handle_request] (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/layer.js:95:5)
at next (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/layer.js:95:5)
at /Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/index.js:281:22
at param (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/index.js:354:14)
at param (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/index.js:365:14)
at Function.process_params (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/index.js:410:3)
at next (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/index.js:275:10)
at next (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/route.js:127:14)
at Hook.expressMiddleware (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/sails/lib/hooks/i18n/index.js:202:14)
at Hook.wrapper [as expressMiddleware] (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/@sailshq/lodash/lib/index.js:3250:19)
at addLocalizationMethod (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/sails/lib/hooks/i18n/index.js:147:35)
at routeTargetFnWrapper (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/sails/lib/router/bind.js:391:9)
at Layer.handle [as handle_request] (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/layer.js:95:5)
at next (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/layer.js:95:5)
at /Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/index.js:281:22
at param (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/index.js:354:14)
at param (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/index.js:365:14)
at Function.process_params (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/index.js:410:3)
at next (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/index.js:275:10)
at next (/Users/benbrookes/Desktop/Dev/reproductions/sails-tests/node_modules/express/lib/router/route.js:127:14)
```
[?] For more help, visit https://sailsjs.com/support
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
This has been reproduced in a fresh sails project.
To reproduce this, create a new sails project and select empty project.
`models/TestModel.js`
```
module.exports = {
attributes: {
name: {
type: "string",
}
}
}
```
`helpers/get-by-id.js`
```
module.exports = {
friendlyName: "Get Record By Id",
description: "Retrieves a single record by Id",
inputs: {
id: {
type: "number",
required: true
}
},
exits: {
recordNotFound: {
description: "The specified record was not found"
}
},
fn: async function(inputs, exits){
await TestModel.findOne({
id: inputs.id
}).catch((err) => {
return exits.error();
}).then((record) => {
if(!record) {
return exits.recordNotFound();
}
return exits.success(record);
});
}
}
```
`controllers/get-by-id.js`
```
module.exports = {
friendlyName: "Get By Id",
inputs: {
id: {
type: "number",
required: true
}
},
exits: {
notFound: {
statusCode: 404,
responseType: ""
},
success: {
statusCode: 200,
responseType: ""
},
serverError: {
statusCode: 500,
responseType: ""
}
},
fn: async function(inputs, exits){
let result = await sails.helpers.getById(inputs.id)
.tolerate("recordNotFound", () => {
return exits.notFound();
}).intercept(() => {
return exits.serverError();
})
return exits.success(result);
}
}
```
API request endpoint: `GET /api/:id`
Original title: Model.findOne causes exit signal error in controller when used in a helper
Contributor guide
Research direction
Start with the reproduced flow in helpers/get-by-id.js and controllers/get-by-id.js, then inspect how the helper's async fn interacts with .tolerate() and .intercept(). Reproduce GET /api/:id and trace the duplicate exit warning; done means the request reaches the intended exit without signaling completion twice.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100