Why does this always return "undefined" - javascript

The following code always returns "undefined"
function sendCommand(cmdJson){
chrome.extension.sendRequest(cmdJson, function(response){
return response;
});
}
I've also tried this variant with the same result
function sendCommand(cmdJson){
var msg;
chrome.extension.sendRequest(cmdJson, function(response){
msg = response;
});
return msg;
}
If I do an alert(response); instead of return response; I get the expected value.

I'm guessing that chrome.extension.sendRequest is asynchronous, in which case sendCommand doesn't return anything. The response-handler inside sendCommand is the one that returns something, but that's not the same, as sendCommand returning something. So when you call sendCommand it returns undefined.
Basically, sendCommand invokes the chrome.extension.sendRequest function, and then returns undefined right away, while the chrome.extension.sendRequest function is still running.
There's no real way to make something asynchronous behave synchronously - it's better to restructure your code.

It is most likely because you are performing an ajax call, which is asynchronous by nature. An asynchronous function cannot return a value since there is no way to know when the asynchronous call will complete.
If you are using jQuery, you have two alternative options to get around this problem. If you are using jQuery 1.5 or later, then you can use Deferred Objects. Deferred Objects are a new object that jQuery allows you to use to interact with asynchronous code.
By default, a jquery ajax function (i.e. $.ajax, $.get, $.post, $.getJSON) returns a Deferred Object, so all you have to do is store your ajax call in a variable and then call available methods listed in the jQuery Deferred Object api. Here is one of the best tutorials I have seen on jQuery Deferred Objects. http://www.erichynds.com/jquery/using-deferreds-in-jquery/
var sendResponse = $.get("/getResponse");
//Somewhere else in your code
sendResponse.success(function(response) {
return response;
});
The other options is to make your jquery ajax call synchronous. You can do this by setting the async ajax property to false.
$.ajax({
url: "someURL",
async: false
});

Related

Get the result inside an object is coming from ajax using getJson

Guys I try access and save the data is coming from ajax using getJson I have some like this
var conversation
conversation = $.getJSON("http://myapi&jsonp=?", function (response) {
return response;
});
console.log(conversation)
I get in my console this
I getting my data inside of responseJSON so I try do some like this
conversation.responseJSON.DATA
but this is give to me undefined what am I doing wrong ? can some one help me pleases
$.getJSON is an asynchronous call, that means that it doesn't get the results instantly, it make a call to the server and the results are available to the the callback function.
You need to put all the code that accesses the results returned from the server inside your callback function
function (response) {
// this is where your code goes.
}
In your code above the variable conversation is a promise, you don't get the results from the promise but with the callback function that runs when the promise resolves.
The usual way of access a promise is with a then call.
var conversationPromise = $.getJSON("http://myapi&jsonp=?");
conversationPromise.then(function(results) {
// Here is where your results are available.
});

Asynchronous jquery - ajax when().then();

I have been trying to read the documents, but I'm having a hard time understanding some concepts:
$.when(function(){
$.ajax({url:'php/Mostrarphp.php', type:'post',data: {queHacer:"MostrarUsuarios"}})
.then(function(success) {
$("#main").html(success);
},function(error) {
$("#main").html(error);
});
})
.then(function() {
console.log("test");
});
What I'm trying to do is for the first function to go into the PHP file and inside that file there is only an include to another file. After that I want to have a console log shown. (This is just practice for, when I need to run functions that retrieve data and will take longer).
The issue here is that the echo is not showing on the application, only shows what is resolved on the then (console.log("test")).
What is the correct way to have this execute the inside function and then the second one?
When you use $.when, you are creating a new promise, one that needs to be resolved. Normally, $.when is used to "combine" multiple promises into one and then run a function once all of them resolve.
What you've passed to $.when is just a function. A function that never gets run. From the docs:
If a single argument is passed to jQuery.when() and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately.
So, that means your console.log("test"); is ran, but your AJAX code is never ran.
You do not not to use $.when here. $.ajax already returns a promise, there's no need to make another one. You can just chain .then() calls.
$.ajax({
url:'php/Mostrarphp.php',
type:'post',
data: {queHacer:"MostrarUsuarios"}
}).then(function(success){
$("#main").html(success);
},function(error){
$("#main").html(error);
}).then(function(){
console.log("test");
});
EDIT: In the comments you said:
[no] matter how much time the inside execution takes to complete, the outside [should] always execute second
If this is what you want, then you will need to create another promise. You can do that and then have it resolve once your "inside" function is complete. I'd suggest wrapping your AJAX code in a function and having it return a promise that you can attach a callback to.
function ajaxCall(){
var d = new $.Deferred;
$.ajax({
url:'php/Mostrarphp.php',
type:'post',
data: {queHacer:"MostrarUsuarios"}
}).then(function(success){
setTimeout(function(){
$("#main").html(success);
d.resolve();
}, 2000);
},function(error){
$("#main").html(error);
d.reject();
});
return d.promise();
}
ajaxCall().then(function(){
console.log("test");
});

How to know which $.ajax promise has resolved?

I'm using jQuery ajax to request data which will then be made into different kinds of charts or tables.
I've put the queries I want to run into an object and send the requests. runQuery() returns a jQuery promise. The data returned when the promise is done is correct. [Edit]Since the ajax requests run asynchronously they may not come back in the order they were issued [/EDIT] and I have no way of know which query the returned data was for.
function refreshData(){
for(var key in baseQueries){
runQuery(baseQueries[key])
.done(function(data){
console.log("Query data for "+key);
// want to call different charting functions
// based upon which results are returned
});
}
};
runQuery(obj) { // "public" function
var params = $.extend({},defaults,obj);
return sendRequest(queryUrl,params)
}
sendRequest(url,data,method){ // "private" function
method = method || "GET";
return $.ajax({
type:method,
url:url,
dataType:"json",
data:data
})
.fail(function(error){
console.log(error);
});
}
In this case the console logs the value of key during the last iteration over the baseQueries object. For example if there are three items in my baseQueries object and the the last item in my baseQueries object is
"This-is-the-last-query":"queryparam1,queryparam2,etc"
Then when all three of the ajax calls resolve I get three logs of "This-is-the-last-query". Which is not helpful because it doesn't tell me which query the data belongs to.
This is similar to the idea of the infamous javascript loop issue but I really don't see how the answer of attaching the value to a DOM element could be used here.
How do I match up which query call goes with which promise? How to I pass the key through the ajax call and return it with the promise data.
Edit
Don't think this is a duplicate of the indicated thread. I see how they are related, but not how to use that to solve this. Suggested duplicate doesn't mention jquery, ajax, promises, or asynchronous issues. It is also marked as a duplicate for another thread that doesn't mention any of those things either.
The solution shown either involves using the dom element to hold the information (which doesn't apply here) needed for the onclick or by adding a closure, but I don't see how to do that when there is already data being returned.
If you pass jQuery ajax a parameter that it knows nothing about, it ignores it and you can access it later.
Here we set a parameter for your extra value (mykey) then we have access to it later for the instance we are using:
function refreshData() {
for (var key in baseQueries) {
runQuery(baseQueries[key], key)
.done(function(data) {
console.log("Query data for " + this.myKey);
// "this" here is the ajax for which the promise (ajax) gets resolved,
// and we return that promise so it works here.
// want to call different charting functions
// based upon which results are returned
});
}
};
runQuery(obj,key) { // "public" function
var params = $.extend({}, defaults, obj);
return sendRequest(queryUrl, params,,key)
}
sendRequest(url, data, method, key) { // "private" function
method = method || "GET";
return $.ajax({
type: method,
url: url,
dataType: "json",
data: data,
myKey:key
})
.fail(function(error) {
console.log(error);
});
}
if you want to check if jquery promise is resolved you can check with jqueryPromise.state() which returns either pending, resolved or rejected depending on state.
If you are sending multiple ajax requests and you want to know when they are completed you can put them into array ([$.ajax(...),$.ajax(...)]) and pass it to
$.when like
var requests = [$.ajax(...),$.ajax(...)];
$.when.apply($, requests).done(function() {
console.log('all requests completed');
});
if you want to build something complex with promises I would suggest using bluebird or less complex rsvp

Return deferred object or null

I have a function that submits some data. Depending on the state of some boolean, I might not want to submit this data. However, the caller is always expecting a deferred object as the return value to check .done() or .fail(). It seems you cannot return null or return nothing when something expects done/fail (makes sense), so I don't know how to return from this async call.
I can hack in a $.Deferred object and immediately resolve/return it, but that seems like bad design. I can't change the calling method here.
How can I return a deferred object or some other return value that satisfies .done() or .fail() without using a deferred object?
function foo(a) {
bar(a).done(function () {
console.log("done");
}).fail(function () {
console.log("fail");
});
}
function bar(a) {
if (a){
// Could create a $.Deferred and resolve it
return;
}
return doAsync();
}
function doAsync() {
var defer = $.Deferred();
defer.resolve();
return defer.promise();
}
foo(false); // fine
foo(true); // error
http://jsfiddle.net/ma4grjj4/2/
The main problem is that it's usually a design smell to have boolean arguments that changes the process flow of a function.
I think you will agree that doing something like the following makes no sense:
function process(doNotProcess) {
if (doNotProcess) return;
//process
}
In the above example, it would make more sense to simply not call on process() to avoid processing.
"What I would do ideally is in foo skip the entire call of bar, but a
lot of stuff happens inside of bar().done that needs to occur in both
cases"
That code should probably be factored out of the done callback and put in a different function, which would allow you to reuse it without having to call bar.
"I can hack in a $.Deferred object and immediately resolve/return it,
but that seems like bad design."
Creating deferred objects and resolving them right away is a quite standard approach when you need to standardize the use of an API that may have a synchronous or asynchronous implementation.
It's a very good practice to do so because it frees the client from having to rely on implementation details.

How can Ajax do asynchronous request and response a synchronous result

I find a fantastic bug when I use jQuery ajax to do a request to web service:
var AjaxResult;
login = function () {
AjaxResult = "";
$.ajax({
type: "POST",
url: KnutBase.getServiceUrl() + "ServiceInterface/HmsPlannerWebService.asmx/AuthenticateLogin",
data: { username: this.username, password: this.password },
dataType: 'jsonp',
success: function (response) {
//the response value is 'success'
AjaxResult = response;
},
error: function (data, status, e) {
alert("error:" + e);
}
});
//alert(AjaxResult);
//if i do not alert a message here, this function will return a null value
//however, i do alert here, then i get a 'success' value.
return AjaxResult;
}
How could this happen.
I am confused as to why the AjaxResult returns its value before the ajax method set response value to it.
Ajax is asynchronous call to your method and it do the processing in the back for server trip. You will not get the result until the success method is called. You can read more about jquery ajax here
You can set async attribute to false of ajax() to make a synchronous call.
EDIT: Using deferreds --
$.Deferred can be used to run code after some other code has completed. Ajax is an excellent example, and all of the jQuery ajax methods (except .load) implement the $.Deferred interface. You can use $.when to watch deferreds. For example:
login = function () {
return $.ajax({...
The deferred gets returned from the method above, so you can do the following:
$.when(login()).done(function (response) { ... });
Any code that needs to be synchronized with the ajax response has to go in the .done callback.
Note that this is not much different than just using the success callback with $.ajax. The point is that all of your work that relies on what is returned from Ajax needs to be done in these callbacks.
Since ajax is asynchronous, return AjaxResult is actually executed before the ajax result completes. You can not return in this way; you need to perform some action in the callback of the ajax requests or use deferred.
It has to do with the fact that AJAX is asynchronous (that's actually the meaning of the first A in it). alert stops the code until you press the button, and the request has time to complete. With no alert, the function proceeds immediately, the AJAX has barely begun its work, and of course the value is still empty.
Generally, you can't have functions return values that they get from AJAX. Set up a callback for it, and deal with it when it comes.
How can Ajax do asynchronous request and return a synchronous result
You can't. It's just impossible. If your code really tries to do that, it will fail.

Categories