Sequelize findOrCreate() -- .catch() block executed after spread() during no error - javascript

My error is similar to this post:
Using sequelize.js as an ORM handler.
queryCondition variable value: {where: {$or: [{username:user.username},{email:user.email}]},defaults:user}
Problem: After successfully saving a user instance to the database, the spread() is called as recommended after invoking findOrCreate(). The function block in spread() is invoked, then immediately after the .catch() block is invoked. No clue why this is happening. Can someone please help?
model.User.findOrCreate(queryCondition).spread(function(user, created){
callback && callback(user, created);
}).catch(function(error){
callback && callback(null, null, error);
});

Found the answer:
Sequelize uses Bluebird.js as it's promise library (check out the package.json file). The documentation explains the spread() method, which is recommended to use in sequelize 3.0 (see post). A section in this document states that spread() invokes all().then(..) under the covers. Therefore, the following change solved my problem using Node.js:
model.User.findOrCreate(queryCondition)
.all().then(function(result, isCreated){
callback && callback(null, result, isCreated);
},
function(error) {
callback && callback(error);
});
Properly resolved promises do not fall into the error block, and actual database errors are caught in the error block. Finally, for those who assumed the error was due to the callback arguments, note that I simply reordered the callback arguments given num8er's suggestion below. :) Hope this helps someone else.

If it's invoking .catch block so it seems to have some issue.
Try to debug it and see the reason:
model.User.findOrCreate(queryCondition).spread(function(user, created){
callback && callback(user, created);
}).catch(function(error){
console.error(queryCondition, error); // add this and check the output
callback && callback(null, null, error);
});
also I saw that Your queryCondition variable is also ok.
{
where:{$or: [{username:user.username},{email:user.email}]},
defaults:user
}
so let's try this annotation:
{
where:{$or: [{username: {$eq: user.username}},{email: {$eq: user.email}}]},
defaults:user
}
read this: http://docs.sequelizejs.com/en/latest/docs/querying/#where
and if with another annotation it will not work properly so I can recommend You to check Your table columns for null, not null fields and compare it with user object to see if there is missing field in user object.
after reading Bergi's comment I'll also recommend You to try to do it like this:
model.User
.findOrCreate(queryCondition)
.then(
function(result, isCreated){
callback && callback(result, isCreated);
},
function(error) {
callback && callback(null, null, error);
});
In case of spread method I think it does not throw exception to be catchable, so in this case:
model.User
.findOrCreate(queryCondition)
.spread(function(result, isCreated){
if(!result) {
return callback && callback('Cannot create user');
}
callback && callback(null, result, isCreated);
});
P.S. Usually in most of packages it's convention to return error as first argument of callback. So I can only guess that problem happens not in Your code example, it happens somewhere outside that waits for callback.
So try to modify callback like this:
callback(user, created); => callback(null, user, created);
callback(null, null, error); => callback(error);

Related

Why is the callback in this method located in a thenable, shouldn't the callback be part of the updateAll method return statement?

According to loopback's official docs, the method updateAll takes 3 parameters: where, data, callback, with callback being required.
Account.deleteSingleHearingTest = function (req, callback) {
Account.findById(req.accessToken.userId)
.then(account => {
if (!account) {
throw new Error('Cannot find user');
}
return app.models.HearingTest.updateAll({ accountId: account.id, id: req.body.hearingTestId }, { isDeleted: new Date() });
})
.then(() => {
callback(null);
})
.catch(error => {
callback(error);
});
}
I can see that the first two parameters are there, however, the callback doesn't seem to part of the method call. Shouldn't callback be part of the updateAlll method?
I'll elaborate on my comment in an answer. I'll bet your code doesn't actually work, you just think it does.
Let's say that the call to updateAll returns something (i.e. does not throw an error) - whether that be null, undefined, true, whatever - then your callback will be called immediately and will not actually wait for your updateAll to perform it's asynchronous operation. Now, if the call to updateAll was sufficiently fast enough, it may appear to you that the code worked when it actually didn't.
This might help illustrate what I mean a bit better:
Promise.resolve()
.then(function() { return undefined; })
.then(function() { console.log('it worked!'); });
Two things you can do (not dependent on each other):
Log the return value of updateAll and see if it's a promise
Just stick to what the docs say and use a callback.
Personally, I'd do 1 and then I'd do 2 :)

RxJS Approach leads to Callback Hell

I would like to use ReactiveJS Observable method for the below use case.
IF MAIN_CACHE EXIST
RETURN OUTPUT
ELSE IF DB CONNECTION EXIST
CACHE MAIN_CACHE (1 Hour)
CACHE FALLBACK_CACHE (3 Days)
RETURN OUTPUT
ELSE IF FALLBACK_CACHE EXIST
RETURN OUTPUT
I got the expected output but i feel this leads to Callback Hell and I think, still its not a good approach and i'm missing something in ReactiveJS Observable key benefits.
Below is my code and the whole code is in JS Bin Link
mainCache.subscribe(function (response) {
console.log(response);
}, function (error) {
dbData.subscribe(function (response) {
console.log(response);
}, function (error) {
console.log('DB CAL Log info', error);
fallbackCache.subscribe(function (response) {
console.log('FALLBACK CACHE SERVED');
console.log(response);
}, function (error) {
console.log('DB CAL Log error', error);
});
});
});
Any lights. much appreciated with working example.
Your implementation indeed is callback hell. You can avoid it by composing your observables with the available rxjs operators, and subscribe at the end when you want to receive the data and have no more transformation. You can have a look at How to do the chain sequence in rxjs and Why we need to use flatMap?, to see how to chain operators, and use only one subscribe at the end of the chaining.
Here your chaining comes from catching errors, so like promises, the best practice is to catch early the errors, as you do, and for that you can use the catch operator`.
mainCache
.do(console.log.bind(console))
.catch(err => dbData.catch(err => {
console.log('DB CAL Log info', error);
return fallbackCache.do(response => {
console.log('FALLBACK CACHE SERVED');
console.log(response);
}).catch(console.log.bind(console, `DB CAL Log error`))
}))
This is only tangential to your use case, but for information, I include also this link, which deals with retrial in case of miss (for example from dbData): retryWhen with backoff

In JavaScript Promises are the reject handler and catch method alternatives [duplicate]

I had a look at the bluebird promise FAQ, in which it mentions that .then(success, fail) is an antipattern. I don't quite understand its explanation as for the try and catch.
What's wrong with the following?
some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
It seems that the example is suggesting the following to be the correct way.
some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
What's the difference?
What's the difference?
The .then() call will return a promise that will be rejected in case the callback throws an error. This means, when your success logger fails, the error would be passed to the following .catch() callback, but not to the fail callback that goes alongside success.
Here's a control flow diagram:
To express it in synchronous code:
// some_promise_call().then(logger.log, logger.log)
then: {
try {
var results = some_call();
} catch(e) {
logger.log(e);
break then;
} // else
logger.log(results);
}
The second log (which is like the first argument to .then()) will only be executed in the case that no exception happened. The labelled block and the break statement feel a bit odd, this is actually what python has try-except-else for (recommended reading!).
// some_promise_call().then(logger.log).catch(logger.log)
try {
var results = some_call();
logger.log(results);
} catch(e) {
logger.log(e);
}
The catch logger will also handle exceptions from the success logger call.
So much for the difference.
I don't quite understand its explanation as for the try and catch
The argument is that usually, you want to catch errors in every step of the processing and that you shouldn't use it in chains. The expectation is that you only have one final handler which handles all errors - while, when you use the "antipattern", errors in some of the then-callbacks are not handled.
However, this pattern is actually very useful: When you want to handle errors that happened in exactly this step, and you want to do something entirely different when no error happened - i.e. when the error is unrecoverable. Be aware that this is branching your control flow. Of course, this is sometimes desired.
What's wrong with the following?
some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
That you had to repeat your callback. You rather want
some_promise_call()
.catch(function(e) {
return e; // it's OK, we'll just log it
})
.done(function(res) {
logger.log(res);
});
You also might consider using .finally() for this.
The two aren't quite identical. The difference is that the first example won't catch an exception that's thrown in your success handler. So if your method should only ever return resolved promises, as is often the case, you need a trailing catch handler (or yet another then with an empty success parameter). Sure, it may be that your then handler doesn't do anything that might potentially fail, in which case using one 2-parameter then could be fine.
But I believe the point of the text you linked to is that then is mostly useful versus callbacks in its ability to chain a bunch of asynchronous steps, and when you actually do this, the 2-parameter form of then subtly doesn't behave quite as expected, for the above reason. It's particularly counterintuitive when used mid-chain.
As someone who's done a lot of complex async stuff and bumped into corners like this more than I care to admit, I really recommend avoiding this anti-pattern and going with the separate handler approach.
By looking at advantages and disadvantages of both we can make a calculated guess as to which is appropriate for the situation.
These are the two main approaches to implementing promises. Both have it's pluses and minus
Catch Approach
some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })
Advantages
All errors are handled by one catch block.
Even catches any exception in the then block.
Chaining of multiple success callbacks
Disadvantages
In case of chaining it becomes difficult to show different error messages.
Success/Error Approach
some_promise_call()
.then(function success(res) { logger.log(res) },
function error(err) { logger.log(err) })
Advantages
You get fine grained error control.
You can have common error handling function for various categories of errors like db error, 500 error etc.
Disavantages
You will still need another catch if you wish to handler errors thrown by the success callback
Simple explain:
In ES2018
When the catch method is called with argument onRejected, the
following steps are taken:
Let promise be the this value.
Return ? Invoke(promise, "then", « undefined, onRejected »).
that means:
promise.then(f1).catch(f2)
equals
promise.then(f1).then(undefiend, f2)
Using .then().catch() lets you enable Promise Chaining which is required to fulfil a workflow. You may need to read some information from database then you want to pass it to an async API then you want to manipulate the response. You may want to push the response back into the database. Handling all these workflows with your concept is doable but very hard to manage. The better solution will be then().then().then().then().catch() which receives all errors in just once catch and lets you keep the maintainability of the code.
Using then() and catch() helps chain success and failure handler on the promise.catch() works on promise returned by then(). It handles,
If promise was rejected. See #3 in the picture
If error occurred in success handler of then(), between line numbers 4 to 7 below. See #2.a in the picture
(Failure callback on then() does not handle this.)
If error occurred in failure handler of then(), line number 8 below. See #3.b in the picture.
1. let promiseRef: Promise = this. aTimetakingTask (false);
2. promiseRef
3. .then(
4. (result) => {
5. /* successfully, resolved promise.
6. Work on data here */
7. },
8. (error) => console.log(error)
9. )
10. .catch( (e) => {
11. /* successfully, resolved promise.
12. Work on data here */
13. });
Note: Many times, failure handler might not be defined if catch() is
written already.
EDIT: reject() result in invoking catch() only if the error
handler in then() is not defined. Notice #3 in the picture to
the catch(). It is invoked when handler in line# 8 and 9 are not
defined.
It makes sense because promise returned by then() does not have an error if a callback is taking care of it.
Instead of words, good example. Following code (if first promise resolved):
Promise.resolve()
.then
(
() => { throw new Error('Error occurs'); },
err => console.log('This error is caught:', err)
);
is identical to:
Promise.resolve()
.catch
(
err => console.log('This error is caught:', err)
)
.then
(
() => { throw new Error('Error occurs'); }
)
But with rejected first promise, this is not identical:
Promise.reject()
.then
(
() => { throw new Error('Error occurs'); },
err => console.log('This error is caught:', err)
);
Promise.reject()
.catch
(
err => console.log('This error is caught:', err)
)
.then
(
() => { throw new Error('Error occurs'); }
)

Dojo: Failed to reach in error callback when using lang.hitch

I'm trying to request the data from server using dojo jsonrest store. While requesting i'm catching the callback to do some stuff. For example
this.myStore.get(paramValue).then(lang.hitch(this, function (res) {
//do something like this.globalVal = res;
}, function (err) {
console.log(err);
//throw error
}));
But the above code only works when the request returns success, i.e. it dose enter in the first block of deferred on success return, but when some error occurred, it failed to reach in the error callback and hence i'm not able to catch the errors returned by server.
If i do the above code without using lang.hitch like this
this.myStore.get(paramValue).then(function (res) {
//do something like this.globalVal = res;
}, function (err) {
console.log(err);
//throw error
});
Then it works. i.e. it will now reach to the error callback as well and i can throw the appropriate error to user.
So why dose this happen, and if lang.hitch is not something that can be used with deferred then what to use?
Thanks
Hitch accepts two arguments, context and the function which is to be executed in the preceding context. At the moment you're using three, that won't work. You're trying to wrap two functions into the same hitch. You'll need to wrap them each in a separate hitch:
this.myStore.get(paramValue).then(
lang.hitch(this, function success (res) {
console.log('Success');
}),
lang.hitch(this, function error (err) {
console.log('Error');
})
);

Parse .then method and chaining | Syntax eludes me

Dear stackoverflow community,
I am using application craft as a JS cloud IDE and integrating Parse's cloud database for storage.
I'm writing a subscription service and want to check to see if a user is already subscribed prior to either authenticating their use or prompting them to sign up. Being an asynchronous call I'm trying to utilise Parse's/Promise's .then method to wait for the server's response before proceeding.
I've read the examples and samples on the Parse site (linked before) yet cannot wrap my head around it.
This code functions, and returns the email address if a match is found:
... *Parse declaration etc*
query.find({
success: function(results){
if(results.length>0){
app.setValue("lblOutput", results[0].attributes.email);
}
else{
app.setValue("lblOutput", "No match.");
}
},
error: function(object, error){
console.log(error.message);
console.log(object);
}
});
My attempt at chaining, most recently this:
query.find().then(function(results) {
if(results){
console.log("Within the Then!");
console.log(results);
}
else{
console.log("Could be an error");
}
});
States that method or property 'success' is invalid for undefined. I have attempted to combine the syntax of the first function (success: ... // error: ...) in the chaining attempt unsuccessfully.
Any advice as to how I could
Check to see if an email exists in the Parse DB, then
Wait until the result comes back for further manipulation with another function
would be greatly appreciated.
Once I have .then() figured out there will be further layers of async waiting.
Cheers,
James
Your syntax for handling then is incorrect, it should be:
query.find().then(
function(results) {
console.log("Within the Then!");
console.log(results);
},
function(error){
console.log("Could be an error"+error);
}
);
the then() function takes one or two functions.
the first is a success handler, and the second is an error handler.
query.find().then(success,error)
This snippet is untested but should be pretty close.
var query = new Parse.Query(Parse.User);
query.equalTo(email, "me#me.com");
query.count().then(
function(resultsCount) {
//success handler
if(resultsCount > 0){
doSomeOtherFunction();
}
},
function(error){
//error handler
console.log("Error:"+error);
}
);
If you have more async work to do, your method should look similar to this, remember that when chaining promises the last then() should contain your error handling.
query.find().then(function(result){
doSomethingAsync(); //must return a promise for chaining to work!
}).then(function(result1){
doSomethingAsync2(); //must return a promise for chaining to work!
}).then(function(result2){
doSomethingAsync3(); //must return a promise for chaining to work!
}).then(null,function(error){
// an alternative way to handle errors
//handles errors for all chained promises.
})

Categories