The "catch" block is not catching the error with one transaction using chain promises
See original GitHub issueWhat you are doing?
I’m using Promises in one transaction.
With my following code, the error is silent and the “catch” is not executed.
var Q = require('q');
var models = require("../models");
var forms = require('./data/forms.json').forms || [];
var createField = function(field, formDB){
return models.field.findOrCreate({
where: {
name: field.apiName,
},
defaults: {
type: field.typeField,
keyItem: field.keyItem,
parentId: field.parentId
}
}).then(function(fieldDB){
fieldDB = fieldDB[0] || fieldDB;
return models.formField.findOrCreate({
where: {
formId: formDB.formId,
fieldId: fieldDB.fieldId,
},
defaults: {
customName: field.customName,
isVisible: field.isVisible,
isRequired: field.isRequired,
position: field.position
}
});
});
};
var createForm = function(form){
return models.form.findOrCreate({
where: {
name: form.name
}
}).then(function(formDB){
formDB = formDB[0] || formDB;
return Q.all(form.fields.map(function(field){
return createField(field, formDB);
}));
});
};
models.sequelize.sync().then(function () {
var result = Q();
forms.forEach(function (form) {
result = result.then(function(){
return createForm(form);
});
});
result.then(function(){
console.log("Success!");
}).catch(function(err){
console.log("Error!"); //********************** Doesn't work ***************************
var msg = err;
});
});
But using transactions, the “catch” is executed (Why? I don’t have any idea about that):
var Q = require('q');
var models = require("../models");
var forms = require('./data/forms.json').forms || [];
var createField = function(field, formDB, t){
return models.field.findOrCreate({
where: {
name: field.apiName,
},
defaults: {
type: field.typeField,
keyItem: field.keyItem,
parentId: field.parentId,
},
transaction: t
}).then(function(fieldDB){
fieldDB = fieldDB[0] || fieldDB;
return models.formField.findOrCreate({
where: {
formId: formDB.formId,
fieldId: fieldDB.fieldId,
},
defaults: {
customName: field.customName,
isVisible: field.isVisible,
isRequired: field.isRequired,
position: field.position
},
transaction: t
});
});
};
var createForm = function(form){
return models.sequelize.transaction(function (t1){
return models.form.findOrCreate({
where: {
name: form.name
},
transaction: t1
}).then(function(formDB){
formDB = formDB[0] || formDB;
return models.sequelize.transaction(function (t2){
return Q.all(form.fields.map(function(field){
return createField(field, formDB, t2);
}));
});
});
});
};
models.sequelize.sync().then(function () {
var result = Q();
forms.forEach(function (form) {
result = result.then(function(){
return createForm(form);
});
});
result.then(function(){
console.log("Success!");
}).catch(function(err){
console.log("Error!"); //******************** Works perfect! ***************************
var msg = err;
});
});
What do you expect to happen?
The catch should be executed with one transaction.
What is actually happening?
The “catch” is not executed and therefore the error is silent.
Output (The error when the catch is executed)
{
"name": "SequelizeUniqueConstraintError",
"message": "Validation error",
"errors": [{
"message": "custom_name must be unique",
"type": "unique violation",
"path": "custom_name",
"value": "Site"
}],
"fields": {
"custom_name": "Site"
}
}
Dialect: postgres Database version: 9.5.3 Sequelize version: 3.23.6
Thanks in advance, Nicholls
Issue Analytics
- State:
- Created 7 years ago
- Reactions:5
- Comments:29 (19 by maintainers)
Top Results From Across the Web
Why catch at the end of promise chain is not ... - Stack Overflow
Looks like the issue is that isUsed is being executed immediately rather than after inBlacklist resolves, so your .then() is being given a ......
Read more >Error handling with promises - The Modern JavaScript Tutorial
Promise chains are great at error handling. When a promise rejects, the control jumps to the closest rejection handler.
Read more >JavaScript Promises and Errors - Peter Coles
This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not...
Read more >Promise.prototype.catch() - JavaScript - MDN Web Docs
The catch method is used for error handling in promise composition. Since it returns a Promise , it can be chained in the...
Read more >Practical Guide to Fp-ts P3: Task, Either, TaskEither
A Promise provides no indication about whether the function can fail. ... When you use a catch block, the error is always of...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
@jdnichollsc I’m going to put this less politely than @janmeier…
Are you bloody mad? I see you are very active on Github so I don’t know how you haven’t managed to understand this already.
Sending a massive load of stuff for people to wade through is rude. What it says is “My time is so important, I’m not going to bother putting any effort into this. Your time is worthless so you can spend an hour of it trying to figure out what’s going on in my huge example”.
I already gave you a long considered answer above working through your previous example as best I could with information you’d given. But you haven’t bothered to engage or reply to that either.
In conclusion: you need to put in some work yourself to help people help you.
Or put another way: wake up or fuck off!
@jdnichollsc Going back to your very first example, does it output
Success!
?I suspect this isn’t actually a matter of the error being “swallowed” in the early example, but is due to the code behaving differently depending on whether you run it in transactions or not.
There are many uses of
findOrCreate()
in your examples, and also you have some parallel execution going on (Q.all(form.fields.map(function(field){ ...
). Within a transaction, thefind()
part offindOrCreate()
can only see database changes made within its own transaction, so it maycreate()
the same row again. But then when the transactions try to commit, you end up with two rows which both can’t be committed, creating theUniqueConstraint
error.You are passing the transaction explicitly between calls, so CLS is not being used. So it should not make any difference whether you use
Q
orSequelize.Promise
. Feel free to use whichever you prefer.What I’m saying is that at this point, I suspect there’s no bug in Sequelize, and it’s a problem with your code.
If you want further help here, I think you first need to try to narrow down this problem yourself. In particular, you haven’t posted the data in
forms
so there’s no way for anyone else reading to replicate the problem.If I were you, I would try to reduce that data down piece by piece and find out at what point the error doesn’t not occur any more. That I think will give you the clue what’s going on.
If I’m wrong, and you do still think it’s a bug in Sequelize, please come back with a single solid example of where an error is being thrown and you think it shouldn’t be. That example should include: model definition, data being used (i.e. what is in the
fields.json
file), and the code - everything someone else needs to get the example running on their own computer and replicate the error. Personally, I find the screencasts hard to follow.I hope you understand that I’m trying to help!