Javascript response and ajax request - javascript

I have the following:
function wikiAjax (searchURL) {
return Promise.resolve($.ajax({
url: searchURL,
jsonp: "callback",
dataType: 'jsonp',
xhrFields: {
withCredentials: true
},
}));
}
$(".search-form").submit(function() {
var searchText = $('#search').val();
var searchURL = "https://en.wikipedia.org/w/api.php?format=json&action=query&generator=search&gsrsearch=" + searchText + "&gsrlimit=15&prop=extracts&exsentences=3&exintro=&explaintext&exlimit=max&callback=JSON_CALLBACK";
console.log(searchURL);
var wikiResponse = wikiAjax(searchURL);
wikiResponse.then(function(data) {
alert(data);
}, function() {
alert("The call has been rejected");
});
});
But i get an answer only if I put a breakpoint somewhere (e.g. at the wikiResponse.then line).
Then it looks like the code is executed before the call returns the result but why? Isn't the promise set properly?
Many thanks in advance.

I think what might be happening here is the browser is executing the default submit event on the form in addition to the ajax call. The result is that the window is unloaded and reloaded.
Try putting:
event.preventDefault();
in the handler.
$(".search-form").submit(function(event) {
event.preventDefault();
var searchText = $('#search').val();
var searchURL = "https://en.wikipedia.org/w/api.php?format=json&action=query&generator=search&gsrsearch=" + searchText + "&gsrlimit=15&prop=extracts&exsentences=3&exintro=&explaintext&exlimit=max&callback=JSON_CALLBACK";
console.log(searchURL);
var wikiResponse = wikiAjax(searchURL);
wikiResponse.then(function(data) {
alert(data);
},
function() {
alert("The call has been rejected");
}
);
});

I think Promise.resolve() is an ES6 feature so unless you explicitly make sure you support it it should not work.
But, lucky for you $.ajax() return a promise in the following format:
var promise = $.ajax({
url: "/myServerScript"
});
promise.done(mySuccessFunction);
promise.fail(myErrorFunction);
(and not with then() and catch() like was written in your code)

It's unnecessary to do Promise.resolve here, because the $.ajax call already returns a promise.
Try this:
function wikiAjax (searchURL) {
return $.ajax({
url: searchURL,
jsonp: "callback",
dataType: 'jsonp',
xhrFields: {
withCredentials: true
}
});
}
$(".search-form").submit(function() {
var searchText = $('#search').val();
var searchURL = "https://en.wikipedia.org/w/api.php?format=json&action=query&generator=search&gsrsearch=" + searchText + "&gsrlimit=15&prop=extracts&exsentences=3&exintro=&explaintext&exlimit=max&callback=JSON_CALLBACK";
console.log(searchURL);
var wikiResponse = wikiAjax(searchURL);
wikiResponse.done(function(data) {
alert(data);
}).fail(function(err) {
alert("The call has been rejected");
});
});
This is a working (and modified to show) plunker: https://plnkr.co/edit/qyc4Tu1waQO6EspomMYL?p=preview

Related

why am I getting undefined at the moment when I click my button?

I want to try to display my notification json through ajax, but however when I try first show me undefined, and then show me my json what am I doing wrong?
$(function (doc, win, $) {
var notification = win.Notification || win.mozNotification || win.webkitNotification;
var $badge = $("#notifications-badge");
var $list = $("#notifications-list");
var $button = $("#notifications-button");
URL_GET_NOTIFICATION = BASE_URL + 'notifications/getNotification';
function check_notifications() {
$.ajax({
type: 'GET',
url: URL_GET_NOTIFICATION,
//data: { timestamp : timestamp },
dataType: 'json',
async: true,
success: function (data) {
console.log(data);
}
});
}
$button.click(function (e) {
alert(check_notifications());
});
}(document, window, jQuery));
All functions return undefined by default when called, unless something else is specified.
You'd get the same with just
function go() {};
alert( go() ); // undefined
And that's basically what you're doing, alerting a function that doesn't return anything.
If you return something from the function, it works
function go() { return 'Hello Kitty' };
alert( go() ); // Hello Kitty
But, as you're using ajax inside the function, you can't really return the result from that, as it's asynchronous and executes some time after the result is returned.
You'd have to use a callback or promise to make it work.
function check_notifications() {
return $.ajax({
type: 'GET',
url: URL_GET_NOTIFICATION,
//data: { timestamp : timestamp },
dataType: 'json'
});
}
$button.click(function (e) {
check_notifications().done(function(data) {
alert(data);
});
});
As a sidenote, use the console when debugging, not alerts.

JavaScript promises with nested AJAX calls are not working

On my code I hava a function with 3 nested AJAX calls, in order for it to work I had to set Async=false.
As I have read that Async=false is deprecated I replaced the Async=false with promises.
This is my function before I edited it:
self.getOrders = function (name) {
var orders= [];
var order= function (item, type1, type2) {
var self = this;
self.order= item;
self.type1= type1;
self.type2= type2;
}
$.ajax({
url: "/API/orders/" + name,
type: "GET",
async: false,
success: function (orderResults) {
var mappedOrders = $.map(orderResults, function (orderItem) {
$.ajax({
url: "/API/orders/property/" + orderItem.id + "/type1",
type: "GET",
async: false,
success: function (property1Results) {
$.ajax({
url: "/API/orders/property/" + orderItem.id + "/type2",
type: "GET",
async: false,
success: function (property2Results) {
orders.push(new order(orderItem, property1Results, property2Results));
}
});
}
});
})
}
});
return orders;
This function worked perfectly, I got the data end everything worked fine.
Then I changed the function to use promises instead of Async=false,
this is the edited function, with promises:
//The begin of the function- same as first one
var orders= [];
var firstPromise = $.ajax({
url: "/API/orders/" + name,
type: "GET"
});
$.when(firstPromise).done(function (orderResults) {
var mappedOrders = $.map(orderResults, function (orderItem) {
var secondPromise = $.ajax({
url: "/API/orders/property/" + orderItem.id + "/type1",
type: "GET"
});
$.when(secondPromise).done(function (property1Results) {
var thirdPromise = $.ajax({
url: "/API/orders/property/" + orderItem.id + "/type2",
type: "GET"
});
$.when(thirdPromise).done(function (property2Results) {
orders.push(new order(orderItem, property1Results, property2Results));
});
});
});
});
return orders;
And the function call:
self.populateOrders = function (name) {
var mappedOrders = $.map(self.service.getOrders(name), function (item) {
return new Order(item)
});
self.orders(mappedOrders);
}
The new function is not working, I'm getting back from the firstPromise a wrong json with backslashes, and the returned orders object is empty.
Any idea what am I doing wrong? I spent so much time on it but couldn't figure it out.
Thanks in advance.
Nested ajax calls inside a loop is a hell to manage. You can do it like this.
Create a promise to notify the caller when the whole process is finished
Wait for all the inner ajax calls to resolve
Resolve you main promise to notify the caller
self.getOrders = function (name) {
var mainDeferred = $.Deferred();
var orders = [];
var order = function (item, type1, type2) {
var self = this;
self.order = item;
self.type1 = type1;
self.type2 = type2;
}
$.ajax({
url: "/API/orders/" + name,
type: "GET",
success: function (orderResults) {
var innerwait = [];
var mappedOrders = $.map(orderResults, function (orderItem) {
var ajax1 = $.ajax({
url: "/API/orders/property/" + orderItem.id + "/type1",
type: "GET"
});
var ajax2 = $.ajax({
url: "/API/orders/property/" + orderItem.id + "/type2",
type: "GET"
});
$.when(ajax1, ajax2).done(function (property1Results, property2Results) {
orders.push(new order(orderItem, property1Results[0], property2Results[0])))
});
innerwait.push(ajax1, ajax2);
});;
$.when.apply(null, innerwait) //make sure to wait for all ajax requests to finish
.done(function () {
mainDeferred.resolve(orders); //now that we are sure the orders array is filled, we can resolve mainDeferred with orders array
});
}
});
return mainDeferred.promise();
}
self.populateOrders = function (name) {
self.service.getOrders(name).done(function (orders) { //use .done() method to wait for the .getOrders() to resolve
var mappedOrders = $.map(orders, function (item) {
return new Order(item)
});
self.orders(mappedOrders);
});
}
In the example, note that I use $.when.apply() to wait for an array of deferreds.
A bug recently introduced in chrome 52 (august 2016) can cause this kind of behavior : answers for nested requested are ignored.
Hoppefully, it will not last long.
https://bugs.chromium.org/p/chromium/issues/detail?id=633696
Try to add cache: false

Button - only do a postback if JavaScript function returns true

I have a button in ASP.NET. When the user clicks the button, I want to make some validation beforehand, so the postback only occurs if the validation method returns true.
My thought was to use the logic of the OnClientClick of the button. If you say OnClientClick="return false;", it won't give a postback, while returning true will. However, that's not working, as the resulting behaviour is it doesn't make a postback even though what my jQuery method returns.
Currently I have:
Markup:
<asp:Button runat="server" ID="ReplyBtn" OnClientClick="return ValidateInput();" OnClick="ReplyBtn_Click" CssClass="btn-large btn-success"
Text="Answer" />
JavaScript:
function ValidateInput() {
var value = stripHtml(CKEDITOR.instances['ReplyBox'].getData()).trim();
var options = {
type: "POST",
url: "../../Services/ForumOperationService.svc/ReplyToPostFeedback",
data: '{"content":"' + value + '"}',
async: false,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$("#StatusReplyLbl").text(msg.ReplyToPostFeedbackResult);
if (msg.ReplyToPostFeedbackResult) {
return false;
} else {
return true;
}
},
error: function () {
return true;
}
};
$.ajax(options);
return false;
}
function stripHtml(str) {
return $('<div />', { html: str }).text();
}
So basically, what's wrong with this code? And how can I perform validation on my button before making a postback?
Your function unconditionally returns false, since you aren't using the response from the ajax object. For example, let us assume your server side script returns the text "OK" if your validation succeeds. You could try something like this:
function ValidateInput() {
var value = stripHtml(CKEDITOR.instances['ReplyBox'].getData()).trim();
var options = {
type: "POST",
url: "../../Services/ForumOperationService.svc/ReplyToPostFeedback",
data: '{"content":"' + value + '"}',
async: false,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$("#StatusReplyLbl").text(msg.ReplyToPostFeedbackResult);
}
};
var resp = $.ajax(options);
return (resp.status==200 && resp.responseText == "OK");
}
Ideally, what you would do is unconditionally return false, and trigger a postback yourself in the success handler.
Not 100% on what you're asking, but I believe the problem is that the function is always returning false even when you expect it to return true from the ajax request?
As mentioned above, ajax running async would cause this not to work but it looks like you're setting async to false.
The issue is your returns.
return true; inside the ajax function returns out of the success function of the ajax call, not the overall function.
I don't think this is the best way to achieve what you're going for, but based on the code you already have, here is what I think you need.
function ValidateInput() {
var replayToPost = false;
var value = stripHtml(CKEDITOR.instances['ReplyBox'].getData()).trim();
var options = {
type: "POST",
url: "../../Services/ForumOperationService.svc/ReplyToPostFeedback",
data: '{"content":"' + value + '"}',
async: false,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$("#StatusReplyLbl").text(msg.ReplyToPostFeedbackResult);
if (msg.ReplyToPostFeedbackResult) {
replayToPost = false;
} else {
replayToPost = true;
}
},
error: function () {
return true;
}
};
$.ajax(options);
return replyToPost;
}
The return result in your ajax function will be a return from the success or error methods therefore it will not bullble up to the ValidateInput() method. You will need to declare a variable outside of the scope of your ajax call and then return that result.
function ValidateInput() {
var value = stripHtml(CKEDITOR.instances['ReplyBox'].getData()).trim();
var result = false;
$.post("../../Services/ForumOperationService.svc/ReplyToPostFeedback", '{"content":"' + value + '"}', function (msg) {
$("#StatusReplyLbl").text(msg.ReplyToPostFeedbackResult);
if (!msg.ReplyToPostFeedbackResult){
result = true;
}
});
return result;
}

jquery function access local javascript variable

New to jQuery and having simple yet confusing problem. ha2.
I am writing this normal javascript function with jQuery function reading xml file. How do I assigned value to the prodPrice variable declared on the top? the script keep returning 0 value, but if I alert the value within the jQuery function, I managed to get the value that I wanted.
Thank you guys.
function getPrice(valprodID)
{
var prodPrice=0;
jQuery.ajax({
type: "GET",
url: "products.xml",
dataType : "xml",
success : function(xml)
{
jQuery(xml).find('prod').each(function(){
var prodID = jQuery(this).find('prodID').text();
if(prodID == valprodID)
{
prodPrice = jQuery(this).find('prodPrice').text();
return false;
}
});
}
})
return prodPrice;
}
That's because $.ajax is performed asynchronously.
And it is a great chance for you to learn how to work with $.Deferred
function getPrice(valprodID)
{
var prodPrice=0;
return jQuery.ajax({
type: "GET",
url: "products.xml",
dataType : "xml"
}).pipe(function(xml)
{
jQuery(xml).find('prod').each(function(){
var prodID = jQuery(this).find('prodID').text();
if(prodID == valprodID)
{
return jQuery(this).find('prodPrice').text();
}
});
});
}
Now you call your getPrice() function in this way:
getPrice(someid).done(function(prodPrice) {
// do what you need with prodPrice
});
Here is an example on jsfiddle: http://jsfiddle.net/zerkms/9MgsX/1/
you can do asynchronous as reported by #xdazz, as #zerkms indicated with Deferred, or anonymous functions:
function getPrice(valprodID, fn)
{
var prodPrice=0;
jQuery.ajax({
type: "GET",
url: "products.xml",
dataType : "xml",
success : function(xml)
{
jQuery(xml).find('prod').each(function(){
var prodID = jQuery(this).find('prodID').text();
if(prodID == valprodID)
{
prodPrice = jQuery(this).find('prodPrice').text();
fn(prodPrice);
}
});
}
})
}
getPrice(1, function(prodPrice) {
/* your code */
})
You need to set the async option to false, or you should do your work in the callback function.

get response from FB Api JavaScript

i try to get a function return in combination with facebook api reqeust.
var g_ret = true;
function uploadImagesFbCounter(anz){
var gid='';
$("div[id ^= 'gallerydetail']").each(function (i) {
gid = this.id.split('-');
gid = parseInt(gid[1]);
})
if(gid==0) return true;
FB.api('/me', function(response) {
  //console.log(response);
  var uid = response.id;
if(!anz){
g_ret = $.ajax({
type: "POST",
async:false,
url: "api/gallerie_anz_speich.php",
data: "uid="+uid+"&op=get&gid="+gid
});
if(g_ret.response >= 20) {
g_ret = false;
}
} else {
g_ret = $.ajax({
type: "POST",
async:false,
url: "api/gallerie_anz_speich.php",
data: "uid="+uid+"&op=set&gid="+gid
});
//console.log(g_ret.response);
g_ret = '<span style="padding:0 5px;">Noch '+(20-g_ret.response)+'Fotos</span>';
console.log(g_ret);
}
});
return g_ret;
}
what ever I do, i get an empty response.... please help!
The API you're using is asynchronous. You can't return a value from your function like that; it's just impossible in such a situation.
Instead, write your API so that its clients pass it a callable function. Inside the Facebook API callback, you can call that function and pass it that "g_ret" string.
function uploadImagesFbCounter(anz, callback){
// ...
FB.api('/me', function(response) {
// ...
callback(g_ret);
});
}
Then when you call your function, instead of:
var result = uploadImagesFbCounter( whatever );
// ... do something with result ...
you'd do this:
uploadImagesFbCounter( whatever, function( result ) {
// ... do something with result ...
});
Getting the user information from Facebook's servers is asynchronous. This means, any code you write after FB.api() does not wait for Facebook to respond. Your browser is not blocked just to wait for Facebook's servers. This is the same concept as AJAX, which I believe you are familiar with because I see you use it in your code.
The common way to "get a return value" from an asynchronous server request is to use a callback function.
function uploadImagesFbCounter(anz, onSuccess){
var gid='';
$("div[id ^= 'gallerydetail']").each(function (i) {
gid = this.id.split('-');
gid = parseInt(gid[1]);
})
if(gid==0) return true;
FB.api('/me', function(response) {
//console.log(response);
var uid = response.id;
if(!anz){
g_ret = $.ajax({
type: "POST",
async:false,
url: "api/gallerie_anz_speich.php",
data: "uid="+uid+"&op=get&gid="+gid
});
if(g_ret.response >= 20) {
g_ret = false;
}
} else {
g_ret = $.ajax({
type: "POST",
async:false,
url: "api/gallerie_anz_speich.php",
data: "uid="+uid+"&op=set&gid="+gid
});
//console.log(g_ret.response);
g_ret = '<span style="padding:0 5px;">Noch '+(20-g_ret.response)+'Fotos</span>';
console.log(g_ret);
}
onSuccess(g_ret);
});
}
uploadImagesFbCounter(
whateverAnzIs,
function(g_ret) {
console.info(g_ret);
}
);

Categories