Uncaught in promise error but getting result from first call - javascript

I have two AJAX calls, the second one depends on the first one, so I decided to use promises. I keep getting Uncaught (in promise) abc123 error in console. Note that abc123 is the id I am expecting from the first AJAX call. The second AJAX call never goes inside success function.
var promise = new Promise(function(reject, resolve) {
$.ajax({
url: url1,
dataType: 'json',
success: function (obj1) {
console.log("Got obj1");
resolve(obj1.id);
}
});
});
promise.then((id)=> {
$.ajax({
url: url2,
dataType: 'json',
success: function (obj2) {
console.log("Got obj2");
}
});
});
The structure looks exactly the same as Basic Example. I am really confused about what I am doing wrong.

You mixed up the order of the callback functions: resolve is the first argument, reject is the second, so you when you called the second one (resolve(obj.id)) you actually rejected your promise.
However, notice that you should not use the Promise constructor anyway when dodging jQuery promises - just use Promise.resolve to cast the jQuery promise that $.ajax returns to a native one:
var promise = Promise.resolve($.ajax({
url: url1,
dataType: 'json'
})).then(obj1 => {
console.log("Got obj1");
return obj1.id;
});
promise.then(id => {
return $.ajax({
//^^^^^^ don't forget this
url: url2,
dataType: 'json'
});
}).then(obj2 => {
console.log("Got obj2");
});

Related

jQuery $.ajaxError preventing ajax promise from being rejected

I have a WebApp with a lot of ajax calls, so I did the following to clean up things:
I defined an ajax call with default values:
$.ajaxCall = function (Params){
return $.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: Params.data,
url: Params.url,
});
};
I defined a global ajax errors handler:
$(document).ajaxError(function( event, xhr, settings, error ) {
if(xhr.hasOwnProperty("responseJSON")
&& xhr.responseJSON.hasOwnProperty("Message")) {
let data = settings.hasOwnProperty("data") ? JSON.parse(settings.data) : null;
switch (xhr.responseJSON.Message) {
// Handle errors
}
}
});
And now I would like somewhere to chain the promise returned by $.ajaxCall (that is the promise object of the deferred object returned by $.ajax):
$.ajaxCall({
url: "WebServices/Workspace_Ajax.asmx/WebMethod",
data: JSON.stringify(DataObject)
})
.then(successAjax, function() {
console.log("Rejected, ajax call failed!");
});
But the reject handler of then is not called, while the $.ajaxError function is well called. I don't understand why the Promise is not rejected (for the case where ajax request works, the Promise is well resolved). What am I missing ?

How to pass a variable from ajax to nested ajax

I'm sending ajax call and getting an answer that I need from the first ajax then I want to pass my result to my nested ajax, my var (result) is null in the nested ajax/settimeout fun, can I pass it ? Am I missing something ?
$.ajax({
url: '#Url.Action("getCustomerGuidId", "Document")',
type: 'POST',
cache: false,
data: { "classNum": currentclassNum},
contentType:'json' ,
dataType:'text',
success: function (result) {
alert(result);**-> is fine - not null**.
// a or result is null when I hit the getCurrentDoc- function althought I get the data I need from getCustomerGuidId function
var a = result;-> tried to pass it to a new var..IDK.. I
thought it will help... it didn't.
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
contentType:'text',
data: a,-> here it's null
success: function (data) {
}
});
}, 2000);
},
error: function (result) {
alert("fail " + result);
}
});
You can try something like this will help to pass value to nested ajax call
function test(){
var myText = 'Hello all !!';
$.get({
//used the jsonplaceholder url for testing
'url':'https://jsonplaceholder.typicode.com/posts/1',
'method':'GET',
success: function (data) {
//updating value of myText
myText = 'welcome';
$.post({
'url':'https://jsonplaceholder.typicode.com/posts',
'method':'POST',
//data.title is the return value from get request to the post request
'data':{'title':data.title},
'success':function (data) {
alert(data.title +'\n' + myText);//your code here ...
}
});
}
});
}
An old question and you've likely moved on, but there's still no accepted answer.
Your setTimeout takes an anonymous function, so you are losing your binding; if you have to use a Timeout for some reason, you need to add .bind(this) to your setTimeout call (see below)
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
contentType:'text',
data: a,
success: function (data) {
}
});
}.bind(this), 2000);
At a guess you're using a Timeout because you want to ensure that your promise (i.e. the first ajax call) is resolving prior to making the nested call.
If that's your intention, you can actually scrap setTimeout completely as you have the nested call in the first ajax success call, which only runs once the promise has been resolved (providing there isn't an error; if so, jQuery would call error rather than success)
Removing setTimeout means you won't lose your binding, and a should still be result (hopefully a is an object, otherwise your second call is also going to experience issues...)
Lastly, after overcoming the binding issue you wouldn't need var a = result; you should be able to pass result directly to your nested ajax call.
Good luck!
In the nested ajax you send a as a param name, not as a param value.
So you can try the following (change param to actual param name which your server expects):
$.ajax({
url: '#Url.Action("getCustomerGuidId", "Document")',
type: 'POST',
cache: false,
data: { "classNum": currentclassNum},
dataType:'text',
success: function (result) {
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
data: {param: result},
success: function (data) {
}
});
}, 2000);
},
error: function (result) {
alert("fail " + result);
}
});

AJAX promise call handling

I have an Ember promise call as below;
var promise = new Ember.RSVP.Promise(function(resolve, reject) {
return $.ajax({
//want this common
url: requestUrl,
type: type, // HTTP method
dataType: dataType, // type of data expected from the API response
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(postData)
})
.done(function(data, status, xhrObject) {
//But want this to be different
// resolve call
})
.fail(function(xhrObject, status, error){
// reject call
});
})
My question is can I use common code for $.ajax(), but have different implementation for done() callback
I can check that by passing some parameter from the calling place.
so basically, I want
if (someparam == 'handleDone1')
call resolve(data)
else
call resolve({data})
You are currently passing a function to done by hard coding a function expression into it.
Replace that with a variable. Pass a value to that variable as a function argument.
Alternatively, don't use done here at all. Just return the return value of $.ajax() and call done() on that in the calling function.
return a promise instead of ajax call. And wrap the ajax call into promise.
checkout the below code. It may helps.
function someFunction(resolve1, reject1) {
return new Ember.RSVP.Promise(function(resolve, reject) {
$.ajax({
//want this common
url: requestUrl,
type: type, // HTTP method
dataType: dataType, // type of data expected from the API response
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(postData)
})
.done(function(data, status, xhrObject) {
//But want this to be different
// resolve call
var dicision = resolve1();
if(dicision){
resolve(data);
} else {
resolve({data});
}
})
.fail(function(xhrObject, status, error){
// reject call
});
}

All AJAX async Requests completed event?

I have a nested ajax requests. The first request returns a list with devices, for each device i do another ajax request to fetch more data. When the nested request is a success i'm appending the data to a <table>.
I need some kind of event that tells me when all requests are complete. How can i do this? See my code below
$.ajax({
type: 'GET',
url: '#Url.Content("~/Service/listAllDevices")',
dataType: 'json',
success: function (data) {
$.each(data.devices.device, function (index, value) {
$.ajax({
type: 'GET',
url: '#Url.Content("~/Service/listLokationLabelsForDevice")' + '?uuid=' + value.uuid,
dataType: 'json',
success: function (data3) {
//Append to table
}
});
});
You can use promises and $.when() to see when all your ajax calls have completed like this:
$.ajax({
type: 'GET',
url: '#Url.Content("~/Service/listAllDevices")',
dataType: 'json',
success: function (data) {
var promises = [];
$.each(data.devices.device, function (index, value) {
promises.push($.ajax({
type: 'GET',
url: '#Url.Content("~/Service/listLokationLabelsForDevice")' + '?uuid=' +
value.uuid,
dataType: 'json',
}));
});
$.when.apply($, promises).done(function() {
// all ajax results are done here
// results from each ajax call are in order in
// arguments[0], arguments[1], ...
// you can now append them all to the table
});
}
});
The basic idea is that you collect the returned promise from each ajax call into an array. You then use jQuery's $.when to have jQuery tell you when all those promises are resolved and to collect all the returned results from them and to keep all the data in the order you requested it in. Then, when the .done() callback from $.when() is called, all the data is available and you can process it all at once, in order.
Note, I've also removed the success handler from the inner ajax call since you can process all the results in the .done() handler.
The event you're looking for is ajaxStop.
$(document).on('ajaxStop', function() {
//do something
});
Reference:
- http://api.jquery.com/ajaxstop/

JavaScript function that returns AJAX call data [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 9 years ago.
I would like to create a JavaScript function which returns the value of a jQuery AJAX call. I would like something like this.
function checkUserIdExists(userid){
return $.ajax({
url: 'theurl',
type: 'GET',
cache: false,
data: {
userid: userid
},
success: function(data){
return data;
}
});
}
I know I can do this by setting async to false but I would rather not.
You can't return data returned by an AJAX call unless you want to call it synchronously (and you don't – trust me). But what you can return is a promise of a data returned by an AJAX call and you can do it actually in a very elegant way.
(UPDATE:
Please note that currently jQuery Promises are not compatible with the Promises/A+ specification - more info in this answer.)
Basically you can return the return value of your $.ajax(...) call:
function checkUserIdExists(userid){
return $.ajax({
url: 'theurl',
type: 'GET',
cache: false,
data: {
userid: userid
}
});
}
and someone who calls your function can use it like this:
checkUserIdExists(userid).success(function (data) {
// do something with data
});
See this post of mine for a better explanation and demos if you are interested.
you can pass in a callback function:
function checkUserIdExists(userid, callback) {
$.ajax({
...
success: callback
});
}
checkUserIdExists(4, function(data) {
});
With jQuery 1.5, you can use the brand-new $.Deferred feature, which is meant for exactly this.
// Assign handlers immediately after making the request,
// and remember the jqxhr object for this request
var jqxhr = $.ajax({ url: "example.php" })
.success(function() { alert("success"); })
.error(function() { alert("error"); })
.complete(function() { alert("complete"); });
// perform other work here ...
// Set another completion function for the request above
jqxhr.complete(function(){ alert("second complete"); });
Source
As of jQuery 1.8, the "success", "error" and "complete" callback are deprecated. Instead you should be using "done", "fail" and "always".
So you could have:
function checkUserIdExists(userid, callback) {
return $.ajax({
url: 'theurl',
type: 'GET',
cache: false,
data: {
userid: userid
}
})
.done(callback)
.fail(function(jqXHR, textStatus, errorThrown) {
// Handle error
});
}
checkUserIdExists(2, function(data) {
console.log(data); // Do what you want with the data returned
});
This isn't how JavaScript asynchronous programming was really meant to be done. Instead, use a callback in your success function to call another function to use your data returned from the server.
Tim, the two scenarios are mutually exclusive; an asynchronous operation will not serve any purpose for, nor will it be able to retrieve returned data.
You should look at an event-enabled infrastructure for your ajax calls

Categories