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');
})
);
Related
I'm getting a little confused with Promises in JavaScript, when currently trying to add some validation and error message handling to a function.
This code works:
hf.tokenize().then(function(payload) {
// ...
}).then(function(payload) {
// ...
}).catch(function(err) {
console.log(err);
});
But does no real error handling, just dumps them in the console. When I try and do this:
hf.tokenize(function(err, payload) {
if (err) {
// Handle error
}
return;
}).then(function(payload) {
// ...
}).then(function(payload) {
// ...
}).catch(function(err) {
console.log(err);
});
I get the following error:
Uncaught TypeError: Cannot read property 'then' of undefined
at HTMLInputElement anonymous
I've looked at a few other questions that give solutions to similar error responses, but the difficulty comes in that I'm not even sure what I'm meant to be doing at this point, or what to return.
Javascript promises are a new syntax but js has had async before the syntax in the form of callbacks. Usually a method has overloads. If you call it without parameters then you can use the Promise syntax and if you call it with parameters then you use the old callback style (where one the the parameters is a function(){ do stuff }).
https://braintree.github.io/braintree-web/current/HostedFields.html#tokenize
callback May be used as the only parameter of the
function if no options are passed in. The second argument, data, is a
tokenizePayload. If no callback is provided, tokenize returns a
function that resolves with a tokenizePayload.
You are mixing them and since you are calling the overload with parameters it doesn't have a return value (the void in -> {Promise|void} hence the "undefined" error.
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);
I have a route that first need to query the database, then with the results, query another web service, then with that result render the page.
I have that flow worked out and am trying to figure out the error handling. Given that i talk to multiple service, I'm trying to massage the error before returning them to express.
Here is the structure of the code for the route:
Models.Episode.findById(request.params.episodeID)
.catch(function (error) {
throw (throwjs.notFound());
})
.then(function (episode) {
if (episode.getUser().id !== request.user.href) {
return next(throwjs.unauthorized("You do not have access to this podcast"));
}
return doSomeOtherAsyncStuff();
})
.then(function (queryResponse) {
renderPage();
})
.catch(function (error) {
next(error);
});
My problem is with the first catch. My goal in this catch is to repackage the error and stop the execution and send the error to express middleware.
With the way it is written above, the execution stops, but my express error handler are not called.
I tried rewriting the first catch as
.catch(function(error){
return next(error);
})
But that does not solve the issue. The only solution i found is to move the catch to the end. But then i lose context of the failure location.
Any clue as to what i'm doing wrong?
Thanks, olivier
I'd recommend taking a different approach so you don't have to rely on long running promise chains. With the following approach, you've decoupled your authorization and and validation to separate middleware, since they're not necessarily a concern of the actual episode handler itself. Plus this approach is more idiomatic to express.
An added bonus is that you're free to pass errors down to an error handler so you further decouple your errors from your route handlers.
function validateEpisode(req, res, next) {
Models.Episode
.findById(req.params.episodeID)
.then(function(episode) {
req.yourApp.episode = episode;
next() // everything's good
})
.catch(function(error) {
// would be better to pass error in next
// so you can have a general error handler
// do something with the actual error
next(throwjs.notFound());
});
}
function authUserByEpisode(req, res, next) {
if (req.yourApp.episode.getUser().id !== req.user.href) {
next(throwjs.unauthorized("You do not have access to this podcast"));
}
next(); // authorized
}
function episodeController(req, res) {
// do something with req.yourApp.episode
}
app.get('/episode/:id', validateEpisode, authUserByEpisode, episodeController)
Well after all, this is related to the throwjs framework I'm using and the fact that I'm using incorrectly
throw (throwjs.notFound());
should be
throw (new throwjs.notFound());
...
what is the real purpose of the error parameter in a call back function?
I've done many node.js courses, and the parameter error always appears in the same way:
something(function(error, result) {
if(error) {
console.log(error);
} else {
// do something with the result.
}
});
This is it? I should always use a console.log(error) if the error is true? I should not send a message to the views?
Can someone show me a good example of dealing with the error parameter in a call back function??
It's difficult do describe what to do with the error as it depends on what something is.
To give you a view how it works please consider this asynchronous pattern:
something(function(error, result){
if(error) {
//exception handler
} else {
//normal execution flow
}
});
as equivalent of synchronous pattern:
try {
var result = something();
//normal execution flow
} catch (error) {
//exception handler
}
So you should do the same thing with the error as you would normally do in catch block.
For some reason this code gives me an uncaught exception error. It seems the catch block is not catching the error. Are try catch blocks scoped in such a way that I cannot throw an error in a nested function, and then expect it to be caught by a catch statement scoped higher up the chain? Some of the sensitive data with in the application that i'm working in has been removed, but it expected that leadInfo[ 0 / 1] would be a 32 character alpha numeric string that I pull from URL parameters.
The underlying issue here is with my AJAX call returning an error from the API and that error not being handled properly within the application. Hence the need for the throw statement. The AJAX call completes fine, and returns a JSON object that does not contain the email address as a property, so I need to handle that in a way that changes the page to reflect that.
jQuery(document).ready(function(){
try {
url = "http://api.com/api/v1/lead/" + leadInfo[1]
jQuery.ajax({
type: 'GET',
contentType: 'application/json',
url: url,
dataType : 'jsonp',
success: function (result) {
result = jQuery.parseJSON(result);
if(!result.data.email){
throw ('New exception');
}
console.log(result);
jQuery('.email').html(result.data.email);
}
});
jQuery('.surveryButton').click(function(){
window.location.replace("http://" + pgInventory.host + pgInventory.path + leadInfo[0] + "&curLeadId=" + leadInfo[1] + "&curViewedPages=0");
});
}
catch(err) {
jQuery('.email').html('your e-mail address');
jQuery('#arrowContent').remove();
}
});
The reason why your try catch block is failing is because an ajax request is asynchronous. The try catch block will execute before the Ajax call and send the request itself, but the error is thrown when the result is returned, AT A LATER POINT IN TIME.
When the try catch block is executed, there is no error. When the error is thrown, there is no try catch. If you need try catch for ajax requests, always put ajax try catch blocks inside the success callback, NEVER outside of it.
Here's how you should do it:
success: function (result) {
try {
result = jQuery.parseJSON(result);
if (!result.data.email) {
throw ('New exception');
}
console.log(result);
jQuery('.email').html(result.data.email);
} catch (exception) {
console.error("bla");
};
}
Due to the asynchronous nature of the callback methods in javascript, the context of the function throwing the error is different compared to the original one. You should do this way:
success: function (result) {
try {
result = jQuery.parseJSON(result);
if(!result.data.email){
throw ('New exception');
}
console.log(result);
jQuery('.email').html(result.data.email);
}
catch(err) {
// Dealing with the error
}
}
I would suggest you to have a look at this excellent article about the (very particular) contexts, closures and bindings in Javascript.
The problem is that ajax is asynchronous by definition. Your exception does not get thrown from within the $.ajax function, but from the callback function on success (which is triggered at a later time).
You should give an error: function(data) {} parameter to it as well, to handle server response errors, and furthermore you should place the try/catch block inside the callback function.
If you really want to catch it outside the callback, then you should consider calling a function rather than throwing an exception, because I don't see how it can be done.