I'm trying to trigger an action after a Javascript object has been created via an AJAX call. My object looks something like this:
function API(uid,accessToken){
$.ajax("path/to/file", {
type: "POST",
data: { user: uid, auth: accessToken },
dataType: "json",
success: function(jsonData) {
arrayname = jsonData[values]
}
});
}
I tried to use JQuery's $.when function to do a callback after the object setup is complete (ie. the array is populated with the ajax response), which looked like this:
$.when( API = new API(uid, accessToken) ).then(function() {
...success function...
});
...but the $.when function triggers with the arrayname values still undefined. From the function's standpoint the deferred object is resolved even though the object values have not yet been set. I've since tried a number of ways to make the API object become deferred based on the completing of the entire ajax call and the setting of the variables, but I'm a bit stuck on the best way to do this.
Any pointers would be most appreciated! Thanks.
You could pass the callback function when you create the object, like so:
function API(uid,accessToken, callback){
$.ajax("path/to/file", {
type: "POST",
data: { user: uid, auth: accessToken },
dataType: "json",
success: function(jsonData) {
arrayname = jsonData[values]
callback(jsonData[values])
}
});
}
and then instantiate the object like so
var api = new API(uid, accessToken, function(array) {
// success function
});
If the problem is due to the "success" callback running after the "then" callbacks, you could try turning success callback into a then callback as well. I don't use JQuery but I guess it would look something like:
function API(uid,accessToken){
return $.ajax("path/to/file", {
type: "POST",
data: { user: uid, auth: accessToken },
dataType: "json",
}).then(function(jsondata){
arrayname = jsondata[values]
});
}
$.when( API = new API(uid, accessToken) ).then(function() {
// ...
});
The reason you use $.when is when you are correlating the callbacks of multiple promises, async tasks, etc. Since jQuery 1.5, all calls to $.ajax and all the wrappers ($.get and $.post) all return promises. Therefore you don't need to wrap this call with the $.when statement unless you want to do $.when(ajaxCall1, ajaxCall2).
Since you want to filter the result from the server, you should use the pipe method of promises:
function API(uid, accessToken)
return $.post(
type: 'POST'
,data: { user: uid, auth: accessToken }
,dataType: 'json'
)
.pipe(function(json) {
return json[values];
})
;
}
This allows you to write your code the way you desire:
API(uid, token)
.then(
// success state (same as promise.done)
function(arrayname /* named from your sample script*/) {
alert('success! ' + arrayname);
}
// error state (same as promise.fail)
,function(jqXHR, status, error) {
console.warn('oh noes!', error);
}
)
.done(function() { /* done #2 */ })
.fail(function() { /* fail #2 */ })
;
Note: promise.pipe() also allows you to filter (change the data passed to) the error callback as well.
Related
i'm not sure if this question has been asked before, i did check but i'm not sure how to actually search for it tbh.
I want to create a reusable function for deleting, confirming based on user decision. I created this simple function to edit element data with object values but i'm not able to run the callback that was set in the first function.
Or maybe it's even possible to somehow return a bool from that function based on user's decision?
Here's the logical example of what i want to achieve
function run(options, cb){
if(options['success']){
cb();
}
}
var options = {success: true};
var cbarray = new Array('id', 'token');
//calling the function and setting the callback
run(options, function(cbarray){
$.ajax({
url: 'blabla',
type: 'post',
data: {id: cbarray[0], token: cbarray[1]},
success: function(resp){
console.log(resp);
}, error: function(resp){
console.log(resp);
}
});
});
It's kinda hard to explain so i created this jsfiddle with my own code
https://jsfiddle.net/43zrqkvm/7/
Maybe i should actually use promises for that? I haven't yet had time to learn promises but maybe i should?
when you defining callback function you'r requesting argument that will be used in function body (in you'r case in ajax options) but in Run function you do not passing it
it must look like this
function run(options,arg, cb){
if(options['success']){
cb(arg);
}
}
var options = {success: true};
var cbarray = new Array('id', 'token');
//calling the function and setting the callback
run(options,cbarray, function(arg){
$.ajax({
url: 'blabla',
type: 'post',
data: {id: arg[0], token: arg[1]},
success: function(resp){
console.log(resp);
}, error: function(resp){
console.log(resp);
}
});
});
Struggling to return a AJAX Result Variable back to JavaScript
Note that the $.ajax call below is synchronous (async: false).
Ajax Call
function getState(callback) {
$.ajax({
url: 'getSearchState.php',
data: { "state": callback },
type: 'GET',
async: false,
success: function(result){
alert(result);
},
error: function(result) {
alert(result);
}
});
}
Ajax PHP
<?php
// Database Setup and Query
while ($row = $xxxxx->fetch(PDO::FETCH_ASSOC)) {
$StateVal = $row['State'];
}
return $StateVal;
?>
Javascript Calling the Function
var URL = District.trim();
var StateURL = getState(URL);
It gets the URL vairable from the function just fine, but doesnt return anything.
Any help would be great!
There are problems with that code both client-side and server-side.
Client-side:
Your getState is never returning anything, so it's no surprise that you don't see anything other than undefined for StateURL.
Don't use synchronous ajax. It makes for horrible UX. But if you really, really want to keep using it, here's how you would:
function getState(state) {
var result; // <=== Where we'll put our result
$.ajax({
url: 'getSearchState.php',
data: {"state": state},
type: 'GET',
async: false,
success: function(data) {
// Remember the result;
result = data;
},
error: function() {
result = /*...whatever you want to use to signal an error */;
}
});
// Return the result
return result;
}
Note that I changed the name of the argument to state, since it's not a callback.
But again, don't use synchronous ajax. Instead, use a callback or promises.
Promise: $.ajax already returns a promise, so just return that directly:
function getState(state) {
var result; // <=== Where we'll put our result
$.ajax({
url: 'getSearchState.php',
data: {"state": state},
type: 'GET',
async: false,
success: function(data) {
// Remember the result;
result = data;
},
error: function() {
result = /*...whatever you want to use to signal an error */;
}
});
// Return the result
return result;
}
Note that I changed the name of the argument to state, since it's not a callback.
But again, don't use synchronous ajax. Instead, use a callback or promises.
Promise:
function getState(state) {
return $.ajax({
url: 'getSearchState.php',
data: {"state": state},
type: 'GET'
});
}
Usage:
getState(URL)
.done(function(StateURL) {
// Use it
})
.fail(function() {
// Failed
});
Callback:
function getState(state, callback) {
$.ajax({
url: 'getSearchState.php',
data: {"state": state},
type: 'GET',
success: function(data) {
// Call the callbback with the result
callback(data);
},
error: function() {
// Call the callback with an error
callback(/*...whatever you want to use tosignal an error */);
}
});
}
Usage:
getState(URL, function(StateURL) {
// Use it, check for error
});
Server-side:
As RiggsFolly pointed out, you're returning a string from your PHP code. But that won't output it. To use it client-side, you need to output it (e.g., echo and similar). And to make it easily consumed by the JavaScript, you probably want to json_encode it to ensure that it's in a format JavaScript can understand:
echo json_encode($stateVal);
Then in your success (or done) function, use JSON.parse on it:
result = JSON.parse(data);
this is jQuery and in this case you can specify context and in success function set variables on that context.... a bit crude solution but it will works. Also take a look on arrow functions and promises from ES6, it can help you a lot and give you new perspective about whole problem.
And one main thing!! Ajax is async by default so you need somehow notify your StateURL when data will be ready (here again promise at you service)
I'm trying to load JSON with a JS function, and then make the JSON objects that are loaded available to other functions in the same namespace. I've tried using return to serve up the array of objects retrieved, but that doesn't work. In the attached example, I've assigned the array of objects to a property in the namespaced object, but when I try to get that array of objects outside the main loadData function, all I get is null.
Here's my JS:
var myObj = {
jsonEndPoint: '/test/test.json',
dataObjects: null
}
myObj.loadData = function () {
$.ajax({
url: 'test.json',
type: 'POST',
dataType: 'json',
success: function (data) {
myObj.dataObjects = data.apiResults[0].league.season.draft.rounds[0].picks;
//console.log(myObj.dataObjects);
},
error: function (xhr, textStatus, errorThrown) {
console.log('Data Load Error: ' + textStatus);
}
});
}()
myObj.displayData = function() {
console.log(myObj.dataObjects)
}()
The full example can be seen here: http://zbl.me/test/index.html
The JSON file I'm loading is here: http://zbl.me/test/test.json
That is because JavaScript is asynchronous in nature — when you attempt to access the myObj.dataObjects in the myObj.displayData function, that object does not yet exist because the AJAX call has not been completed yet.
What you could do is that ensure that all functions that require newly added data from the AJAX call be run only when a .done() promise has been delivered from your AJAX call, by using $.when(). The logic is quite straightforward:
myObj.loadData() is now exclusively used to make the AJAX call. With regards to how we handle the done and fail events (which are previously .success() and .error() callbacks), we delegate that logic to the next function.
myObj.displayData() is now use to evaluate the promise returned by your AJAX call made with myObj.loadData(). You use $.when() to fetch the promise, and then simply chain .done() to deal with a successful call and .fail() to deal with the opposite :)
Here's your improved code:
var myObj = {
jsonEndPoint: '/test/test.json',
dataObjects: null
}
myObj.loadData = function () {
// We return the AJAX object so that we can evaluate the state later
// This is very simple :)
return $.ajax({
url: 'test.json',
type: 'POST',
dataType: 'json'
});
}()
myObj.displayData = function() {
// Instead of using the deprecated .success() and .error()
// ... we use .done() and .fail()
$.when(myObj.loadData).done(function(data) {
myObj.dataObjects = data.apiResults[0].league.season.draft.rounds[0].picks;
}).fail(function(xhr, textStatus, errorThrown) {
console.log('Data Load Error: ' + textStatus);
});
}()
If you are unsure, you can check the dummy code here: http://jsfiddle.net/teddyrised/5rbd2eqq/1/ I have used the built-in JSON response from JSfiddle to generate an artificial response, but the logic is exactly the same as yours.
Your displayData method is called even before the ajax is completed. So you either need to call displayData in the success callback of ajax or change the structure a bit so that its easy to call.
Why don't you instead do something like this
var myObj = {
jsonEndPoint: '/test/test.json',
dataObjects: null,
displayData: function() {
console.log(this.dataObjects);
},
loadData: function() {
$.ajax({
context: this,
url: 'test.json',
type: 'GET',
dataType: 'json',
success: function(data) {
this.dataObjects = data.apiResults[0].league.season.draft.rounds[0].picks;
console.log(myObj.dataObjects);
this.displayData();
},
error: function(xhr, textStatus, errorThrown) {
console.log('Data Load Error: ' + textStatus);
}
});
}
};
myObj.loadData();
Here is a demo
I need to display the comments on my page by fetching from database.
I am able to get dummy test data from .json file but when I try to connect it with data base url it is not getting the data.
I am using js handlebar template to loop the data in html page.
Here is my js to fecth the data
var getData = function () {
console.group("getData()", "Fetching data from server at", R.settings.endPoints.incoming.getData);
var promise = $.ajax({
url: R.settings.endPoints.incoming.getData
});
console.log("getData()", "Returing the promise", { promise: promise });
console.groupEnd();
return promise;
};
DB url is set with .getdata like below
endPoints: {
incoming: {
getData: "http://localhost:8080/rest/review/getReview"
},
outgoing: {
sendData: "http://localhost:8080/rest/review/createReview"
}
}
jQuery's $.ajax function is asynchronous by default so you need to put your processing/display code into the deferred.done method like so:
var promise;
$.ajax({
url: R.settings.endPoints.incoming.getData
})
.done(function( msg ) {
console.log(msg);
promise = msg;
});
However, if you want to perform a synchronous request, do something like this:
var promise = $.ajax({
url: R.settings.endPoints.incoming.getData,
async: false
});
Note that according to the official documentation:
As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated;
you must use the success/error/complete callback options instead of the
corresponding methods of the jqXHR object such as jqXHR.done() or the
deprecated jqXHR.success().
If I have to leverage niceties of jQuery AJAX API and set my own custom settings for each ajax call my app makes like below:
Say I have a page which displays employee information within table by making ajax calls to some API.
define(["jQuery"], function($) {
var infoTable = function (options) {
function init() {
// Provide success callback
options.success_callback = "renderData";
getData();
}
function renderData() {
// This callback function won't be called as it is not
// in global scope and instead $.ajax will try to look
// for function named 'renderData' in global scope.
// How do I pass callbacks defined within requirejs define blocks?
}
function getData() {
$.ajax({
url: options.apiURL,
dataType: options.format,
data: {
format: options.format,
APIKey: options.APIKey,
source: options.source,
sourceData: options.sourceData,
count: options.count,
authMode: options.authMode
},
method: options.method,
jsonpCallback: options.jsonpCallback,
success: options.success_callback,
error: options.error_callback,
timeout: options.timeout
});
}
}
return {
init: init
}
}
How do I achieve this?
I know we can use JSONP request as require calls but that restricts me to using jsonp, making GET requests and all other features $.ajax offers.
This example would let you either use a default success callback, or provide an override, using:
success: options.successCallback || renderData
(The example uses jsfiddle rest URLs - this fact is unimportant, and stripped out the data object to keep the example short)
define("mymodule", ["jquery"], function($) {
function renderData() {
console.log("inside callback");
}
function getData(options) {
$.ajax({
url: options.apiURL,
dataType: options.format,
method: options.method,
jsonpCallback: options.jsonpCallback,
success: options.successCallback || renderData,
error: null,
timeout: options.timeout
});
}
return {
getData: getData
}
});
require(["mymodule"], function(m) {
console.log(m, m.getData({
apiURL: "/echo/json/"
}));
console.log(m, m.getData({
successCallback: function() { console.log("outside callback"); },
apiURL: "/echo/json/"
}));
});
Would print:
GET http://fiddle.jshell.net/echo/json/ 200 OK 263ms
Object { getData=getData()} undefined
GET http://fiddle.jshell.net/echo/json/ 200 OK 160ms
Object { getData=getData()} undefined
inside callback
outside callback