Hello i have a problem with ajax and two callbacks code look like that
loadTasks(function(tasks) {
taskhtml = whatStatus(tasks);
loadSupportList(function(tasks) {
supporthtml = support(tasks);
$("#devtask-table").html(
titleDraw() + "<tbody>" + supporthtml + taskhtml
+ "</tbody>");
hideCurtain();
});
});
And it's work fine when loadSupportList or loadTasks have records. But when one of them don't i get Error, status = parsererror, error thrown: SyntaxError: Unexpected end of input. And it jump off function and leave me with nothing. My ajax function looks that way :
function loadSupportList(callback) {
$.ajax({
type : "POST",
url : url,
data : {
userId : userId,
sessionId : sessionId
},
success : function(data) {
callback(data['tasks']);
},
error : function(jqXHR, textStatus, errorThrown) {
console.log("Error, status = " + textStatus + ", " + "error thrown: "
+ errorThrown);
}
});
}
And i dont know what to change, to ignore(?) or made some json with ('success')? Is there a way? Thanks for your time.
I make something silly, but its work so it's not silly
loadTasks(function(tasks) {
taskhtml = whatStatus(tasks);
$("#devtask-table").html(
titleDraw() + "<tbody>" + supporthtml + taskhtml
+ "</tbody>");
loadSupportList(function(tasks) {
supporthtml = support(tasks);
$("#devtask-table").html(
titleDraw() + "<tbody>" + supporthtml + taskhtml
+ "</tbody>");
hideCurtain();
});
});
assuming tasks returns an array... update your loadSupportList function like this..
success : function(data) {
var ret = [];
if(
'object' == typeof data &&
'undefined' != typeof data.tasks
) ret = data.tasks;
callback(ret);
}
Related
I have a small weather app. I get the weather data via "POST" request and append it to the document, that works good.
The users can query the weather by City, now I wanted to load an image of that city with a separate jQuery $Ajax() request.
However, I always get the same result.
The app relevant app structure looks like this:
<input id="getIt" name="cityajax" type="text" class="ghost-input"
placeholder="Enter a City" required> // get user input, querying a city
<button id="submit">Submit</button>
<span class="humidLogo">Current humidity:</span> <i class="fas fa-temperature-low" ></i> <span class="apiHumidity"> % </span>
<div class="FlickResponse"></div> // flickrResposnse gets appended here
</div>
The CSS is not relevant, so I follow up with the relevant JS function right away:
var destination = $("#getIt").val(); // cache the user input, I am not sure I have to listen for a change event here and then update the state.
var flickerAPI =
"https://api.flickr.com/services/feeds/photos_public.gne?format=json&tags=" +
destination; // the url to get access the api
$.ajax({
url: flickerAPI,
dataType: "jsonp", // jsonp
jsonpCallback: "jsonFlickrFeed", // add this property
success: function(result, status, xhr) {
$(".FlickResponse").html(""); // here I want to empty the contents of the target div, but this never happens
$.each(result.items, function(i, item) {
$("<img>")
.attr("src", item.media.m)
.addClass("oneSizeFitsAll")
.appendTo(".FlickResponse");
if (i === 1) {
return false;
}
});
},
error: function(xhr, status, error) {
console.log(xhr);
$(".FlickResponse").html(
"Result: " +
status +
" " +
error +
" " +
xhr.status +
" " +
xhr.statusText
);
}
});
That is all. So why do I always get the same response from the API? Do I have to listen to change events on the input field? Because the POSt request work without a change event listener.
Is it because I am querying 2 APIs and I am using the same input field for the value(stupid question, but you never know x).?
Here is a Codepen with the full code, just enter a city and click the submit button:
https://codepen.io/damPop/pen/qLgRvp?editors=1010
I would pull the image retrieval (and weather lookup) into another function as shown below, then you're good!
I've forked to another codepen: updated example
function loadDestinationImage() {
var destination = ($("#getIt").val());
var flickerAPI = "https://api.flickr.com/services/feeds/photos_public.gne?format=json&tags=" + destination;
$.ajax({
url: flickerAPI,
dataType: "jsonp", // jsonp
jsonpCallback: 'jsonFlickrFeed', // add this property
success: function (result, status, xhr) {
$(".FlickResponse").html("");
$.each(result.items, function (i, item) {
$("<img>").attr("src", item.media.m).addClass("oneSizeFitsAll").appendTo(".FlickResponse");
if (i === 1) {
return false;
}
});
},
error: function (xhr, status, error) {
console.log(xhr)
$(".FlickResponse").html("Result: " + status + " " + error + " " + xhr.status + " " + xhr.statusText)
}
});
}
I'd do the same with the weather:
function loadWeather() {
var destination = ($("#getIt").val());
$.post("https://api.openweathermap.org/data/2.5/weather?q=" +
destination +
"&units=metric&appid=15c9456e587b8b790a9092494bdec5ff",
function (result, status, xhr) {
var APIresponded = result["main"]["temp"];
var APIweather = result["weather"][0]["description"];
var sunGoing = result["sys"]["sunset"];
var output = destination.capitalize();
var humidValue = result["main"]["humidity"];
var windy = result["wind"]["speed"];
var windDirection = result["wind"]["deg"];
if (windDirection <= 90) {
windDirection = "southwest"
}
if (windDirection <= 180) {
windDirection = "northwest"
}
if (windDirection <= 270) {
windDirection = "northeast"
}
if (windDirection <= 360) {
windDirection = "southeast"
}
if (APIweather.includes("snow")) {
$('#displaySky').addClass('far fa-snowflake');
}
if (APIweather.includes("rain")) {
$('#displaySky').addClass('fas fa-cloud-rain');
}
if (APIweather.includes("overcast")) {
$('#displaySky').addClass('fas fa-smog');
}
if (APIweather.includes("sun") || APIweather.includes("clear")) {
$('#displaySky').addClass('fas fa-sun');
}
if (APIweather.includes("scattered")) {
$('#displaySky').addClass('fas fa-cloud-sun');
}
$("#message").html("The temperature in " + output + " is : " + APIresponded + " degrees. The sky looks like this: ");
$(".apiHumidity").text(humidValue + " %");
$('.apiWind').html(windy + 'km per hour. The wind direction is ' + windDirection);
console.log(APIweather);
}
).fail(function (xhr, status, error) {
alert("Result: " + status + " " + error + " " +
xhr.status + " " + xhr.statusText);
});
}
And call from the submit function:
$("#submit").click(function (e) {
loadDestinationImage();
loadWeather();
});
I'm getting a "Uncaught SyntaxError: Unexpected end of input" error, when i take out the below snippet the error goes away. Maybe its because ive been up all night but i cant for the life of me find the issue. Can anyone please shed some light?
$.ajax({
url: "scripts/getWorkerPendingJobs.php",
type: "get",
data: {uid: userId},
success: function(dataa) {
var daa = JSON.parse(dataa);
var amtt = parseInt(daa.length);
var htmll = "";
if (amtt > 0) {
$.each(daa, function(indexx) {
var status;
var acc = daa[indexx].accepted.toString();
if (acc == 1) {
status = "Pending";
}
if (acc == 2) {
status = "Accepted";
}
htmll += '<li><img src="./noimage.png" /><h3>' + daa[indexx].dateadded + ' | ' + daa[indexx].shortdesc + '</h3><h2>Status : ' + status + '</h2><p>' + daa[indexx].description + '</p></li>';
$('.worker-applied-jobs').html(htmll).promise().done(function() {
$(this).listview("refresh");
});
});
} else {
$('.worker-applied-jobs').html('<p style="margin-left:10px;">You have not applied for any jobs.</p>');
}
}
});
I have created buttons using javascript, these buttons are created onload by the javascript page. The number of buttons created, as well as the button attributes (id, name), depend on the info that is fetched from a database table. Now I need to use the buttons independently, but I don't know the id in advance so I could mention it on any function, please help.
var CABLE_BOM_ALT_QUERY_PAGE = 'GetAltFromBom.json.aspx';
var WIRE_TYPE = 'AVSSXF2B';
var WIRE_LENGTH = 2000;
$(document).ready(function () {
FetchCableBom();
});
function FetchCableBom() {
$.ajax({
url: CABLE_BOM_ALT_QUERY_PAGE
, data: "WireType=" + WIRE_TYPE + "&WireLength=" + WIRE_LENGTH
, dataType: 'json'
, success: DisplayButtons
, error: ErrorHandler
, async: false
});
}
function createButtons(tbID, tbClass, tbType, tbValue, onClick) {
return '\n<input'
+ (tbID ? ' id=\'' + tbID + '\'' : '')
+ (tbClass ? ' class=\'' + tbClass + '\'' : '')
+ (tbType ? ' type=\'' + tbType + '\'' : '')
+ (tbValue ? ' value=\'' + tbValue + '\'' : '')
+ (onClick ? ' onclick=\''+ onClick + '\'':'')
+ '>';
}
function DisplayButtons(cableData) {
var newContent = '';
$.each(cableData, function (i, item) {
newContent += createButtons(item.CommonCable, null, "submit", item.CommonCable, toggle);
});
$('#Categories').html(newContent);
}
function toggle() {
console.log("P#ssw0rd");
return;
}
function ErrorHandler() {
alert('ERROR: ' + jqXHR.status + '\r\nURL: ' + this.url + '\r\nContact the I.T Department.');
}
Even after reading it a few times I am not quite sure I know what you are trying to do. But here is my guess: You have some result set containing button attributes which come from a database. And you want these buttons "independently", I assume without having queried the database, because you need some kind of Id.
Have you thought about statically pre-populating your result set whenever the database hasn't been queried yet? Something along the lines of this:
if (hasDatabaseResult) {
buttonData = getDatabaseResult();
} else {
buttonData = [ {id : 1, name : "First record"} ]
}
I have web methods that are called via AJAX in a .Net 4.0 web app. In many cases, the AJAX calls are made repeatedly in a for loop. My problem is, the information the web method is syncing to my server is time stamped and therefore must be synced in the order in which I am sending it to AJAX. Unfortunately, it seems whatever finishes first, simply finishes first and the time stamps are all out of order. I need to basically queue up my AJAX requests so that they execute in order rather than Asynchronously, which I know is the A in AJAX so this might be a totally dumb question.
How do I force the order of execution for AJAX calls done in a for loop?
Edit: Some code
for (var i = 0; i < itemCnt - 1; i++) {
try {
key = items[i];
item = localStorage.getItem(key);
vals = item.split(",");
type = getType(key);
if (type == "Status") {
var Call = key.substring(7, 17);
var OldStat = vals[0];
var NewStat = vals[1];
var Date1 = vals[2];
var Time1 = vals[3];
var miles = vals[4];
try {
stat(Call, OldStat, NewStat, Date1, Time1, miles, key);
}
catch (e) {
alert("Status " + e);
return;
}
}
else if (type == "Notes") {
var Call = key.substring(6, 16);
var Notes = item;
try {
addNotes(Call, Notes);
}
catch (e) {
alert("Notes " + e);
return;
}
}
else if (key == "StartNCTime" || key == "EndNCTime") {
var TechID = vals[0];
var Date = vals[1];
var Time = vals[2];
var Activity = vals[3];
var Location = vals[4];
var Type = vals[5];
try {
logTime(TechID, Date, Time, Activity, Location, Type,
}
catch (e) {
alert(key + ' ' + e);
return;
}
}
}
catch (e) {
alert(key + ' ' + e);
return;
}
}
function stat(Call, OldStat, NewStat, Date1, Time1, miles, key) {
$.ajax({
type: "POST",
dataType: "json",
contentType: "application/json",
url: "Service.asmx/update_Stat",
data: '{ CallNumber:"' + Call + '", OldStat:"' + OldStat + '", NewStat:"' + NewStat + '", Date1:"' + Date1 + '", Time1:"' + Time1 + '", Miles: "' + miles + '"}',
success: function (data) { },
error: function (xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert("Sync Update Stat: " + err.Message);
location = location;
}
});
}
function logTime(TechID, Date, Time, Activity, Location, Type, key) {
$.ajax({
type: "POST",
dataType: "json",
contentType: "application/json",
url: "Service.asmx/nonCallTime",
data: '{ TechID:"' + TechID + '", Date1:"' + Date + '", Time1:"' + Time + '", Activity:"' + Activity + '", Location:"' + Location + '", Type: "' + Type + '"}',
success: function (data) { },
error: function (xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert("Sync Non Call Time: " + err.Message);
location = location;
}
});
}
function addNotes(Call, Notes) {
$.ajax({
type: "POST",
dataType: "json",
contentType: "application/json",
url: "Service.asmx/addNote",
data: '{ Call:"' + Call + '", Notes:"' + Notes + '"}',
success: function (data) { },
error: function (xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert("Sync Notes: " + err.Message);
location = location;
}
});
}
You have to use callbacks.
function ajax1(){
//..some code
//on ajax success:
ajax2();
}
//etcetera...
Or might I suggest using a javascript library like jQuery to synchronize your ajax requests for you.
set the third parameter in xmlhttp object's open method to false to make it synchronous.
http://www.w3schools.com/ajax/ajax_xmlhttprequest_send.asp
A general pattern for making actions serial would be such:
function doAjax(data, cb) {
...
// when ready call cb
}
(function (next) {
var xhr = doAjax(data, next);
})(function (next) {
var xhr = doAjax(data, next);
})(function (next) {
doAjax(data);
});
Doing so in a for loop would require recursion.
(function next() {
if ( i < n ) {
doAjax(data[i++], next);
}
})();
This is just freakin weird to me. So if I don't
function BindAlbumAndPhotoData()
{
// Get an array of all the user's Albums
var aAlbums = GetAllAlbums(userID, token);
alert("aAlbums: " + aAlbums);
if (aAlbums == null || aAlbums == "undefined")
return;
// Set the default albumID
var defaultAlbumID = aAlbums[0].id;
};
So I get an undefined error on the line var defaultAlbumID = aAlbums[0].id; if I don't uncomment the alert("aAlbums: " + aAlbums);
what the heck? If I comment out alert("aAlbums: " + aAlbums); then I get an undefined for the var defaultAlbumID = aAlbums[0].id;
This is so weird. I've been working all night to figure out why I kept getting an undefined for the aAlbum[0] and as soon as I add back an alert that I used to have above it, all is fine...makes no sense to me.
Here's the full code of GetAllAlbums:
function GetAllAlbums(userID, accessToken)
{
var aAlbums = []; // array
var uri = "/" + userID + "/albums?access_token=" + accessToken;
alert("uri: " + uri);
FB.api(uri, function (response)
{
// check for a valid response
if (!response || response.error)
{
alert("error occured");
return;
}
for (var i = 0, l = response.data.length; i < l; i++)
{
alert("Album #: " + i + "\r\n" +
"response.data[i].id: " + response.data[i].id + "\r\n" +
"response.data[i].name: " + response.data[i].name + "\r\n" +
"response.data[i].count: " + response.data[i].count + "\r\n" +
"response.data[i].link: " + response.data[i].link
);
aAlbums[i] = new Album(
response.data[i].id,
response.data[i].name,
response.data[i].count,
response.data[i].link
);
alert("aAlbums[" + i + "].id : " + aAlbums[i].id);
}
});
return aAlbums;
}
so I'm not returning the array until I hit the callback of the FB.api async call so I don't see how my defaultAlbumID = aAlbums[0].id; line of code is executing before I have a valid array of data back. When I put in the alert, ovbvioulsly it's delaying before it hits my line defaultAlbumID = aAlbums[0].id; causing it to I guess luckily have data beacuse the async FB.api call is done but again I don't see how that's even possible to have an issue like this when I'm waiting for the call before proceeding on and returning the array to aAlbums in my BindAlbumAndPhotoData() method.
UPDATE #3
function BindAlbumAndPhotoData()
{
GetAllAlbums(userID, accessToken, function (aAlbums)
{
alert("we're back and should have data");
if (aAlbums === null || aAlbums === undefined) {
alert("array is empty");
return false;
}
var defaultAlbumID = aAlbums[0].id;
// Set the default albumID
var defaultAlbumID = aAlbums[0].id;
// Bind the album dropdown
alert(" defaultAlbumID: " + defaultAlbumID);
});
};
function GetAllAlbums(userID, accessToken, callbackFunctionSuccess)
{
var aAlbums = []; // array
var uri = "/" + userID + "/albums?access_token=" + accessToken;
FB.api(uri, function (response)
{
// check for a valid response
if (!response || response.error)
{
alert("error occured");
return;
}
for (var i = 0, l = response.data.length; i < l; i++)
{
alert("Album #: " + i + "\r\n" +
"response.data[i].id: " + response.data[i].id + "\r\n" +
"response.data[i].name: " + response.data[i].name + "\r\n" +
"response.data[i].count: " + response.data[i].count + "\r\n" +
"response.data[i].link: " + response.data[i].link
);
aAlbums[i] = new Album(
response.data[i].id,
response.data[i].name,
response.data[i].count,
response.data[i].link
);
alert("aAlbums[" + i + "].id : " + aAlbums[i].id);
}
// pass the array back to the callback function sent as a param to the GetAllAlbums method here
callbackFunctionSuccess(aAlbums);
});
}
It's not hitting my alert in the callback. I must still be doing something wrong here.
UPDATE #4 - for some reason it's not hitting my FB.api callback now.
function GetAllAlbums(userID, accessToken, callbackFunctionSuccess)
{
var aAlbums = []; // array
var uri = "/" + userID + "/albums?access_token=" + accessToken;
alert("uri: " + uri);
FB.api(uri, function (response)
{
// check for a valid response
if (!response || response.error)
{
alert("error occured");
return;
}
for (var i = 0, l = response.data.length; i < l; i++) {
alert("Album #: " + i + "\r\n" +
"response.data[i].id: " + response.data[i].id + "\r\n" +
"response.data[i].name: " + response.data[i].name + "\r\n" +
"response.data[i].count: " + response.data[i].count + "\r\n" +
"response.data[i].link: " + response.data[i].link
);
aAlbums[i] = new Album(
response.data[i].id,
response.data[i].name,
response.data[i].count,
response.data[i].link
);
alert("aAlbums[" + i + "].id : " + aAlbums[i].id);
}
alert("about to pass back the array to the callback function");
// pass the array back to the callback function sent as a param to the GetAllAlbums method here
callbackFunctionSuccess(aAlbums);
});
}
function BindAlbumAndPhotoData()
{
// Get an array of all the user's Albums
GetAllAlbums(userID, token, function(aAlbums){
// Set the default albumID
var defaultAlbumID = aAlbums[0].id;
});
};
and then in the GetAllAlbums function call the success function when you have the data back
//********* AFTER THE BREAK *******//
In response to the updated question: The FB API is mostly asynchronous, and will keep executing other code while it waits. So using your code, all I have done is passed in the function, and then call the function you've passed it at the end
function GetAllAlbums(userID, accessToken, funcSuccess)
{
var aAlbums = []; // array
var uri = "/" + userID + "/albums?access_token=" + accessToken;
alert("uri: " + uri);
FB.api(uri, function (response)
{
// check for a valid response
if (!response || response.error)
{
alert("error occured");
return;
}
for (var i = 0, l = response.data.length; i < l; i++)
{
alert("Album #: " + i + "\r\n" +
"response.data[i].id: " + response.data[i].id + "\r\n" +
"response.data[i].name: " + response.data[i].name + "\r\n" +
"response.data[i].count: " + response.data[i].count + "\r\n" +
"response.data[i].link: " + response.data[i].link
);
aAlbums[i] = new Album(
response.data[i].id,
response.data[i].name,
response.data[i].count,
response.data[i].link
);
alert("aAlbums[" + i + "].id : " + aAlbums[i].id);
}
funcSuccess(aAlbums);
});
}
Is your function GetAllAlbums() doing some HTTP requests? If so then you need to either make that call synchronous or you need to put your code into a function and pass that as a callback to the Ajax request.
Try three equals signs instead of two, and also... return false rather than nothing at all.
if (aAlbums === null || aAlbums === undefined)
return false;
Also, undefined doesn't need to be in quotes, otherwise, it's just considered a string with a value of "undefined"
On an added note, it's probably better to ALSO check if aAlbums is actually an array before you decide to return a key from it.
if ( aAlbums === null
|| aAlbums === undefined
|| (typeof(aAlbums)=='object'&& !(aAlbums instanceof Array))
} return false;
Try modifying your condition like this:
if (typeof aAlbums == 'undefined')
return;
Also make sure that aAlbums has values and is an array:
alert(aAlbums.length);
Or:
for(var i = 0; i < aAlbums.length; i++)
{
alert(aAlbums[i].id);
}