A newbie here working with FourSquare API. I'm not sure if I'm doing this correctly, but I need to pull in data from a search via "https://developer.foursquare.com/docs/venues/search". However, along with that I'd like to have more details about each venue such as their hours of operation and other details about the venue aside from the generic contact and name. What I've done is nested an ajax call-the search api and then within search venue, do another venue detail search.
$.when(
$.ajax({
url: "https://api.foursquare.com/v2/venues/search?limit=4&"+$this.settings.key+"&ll="+$this.currentLocation.coord+"&intent=checkin",
data: inputData,
dataType: "json",
success: function(res, req) {
var data = res.response.venues;
$('.results').find('.loading').addClass('hide');
$.each(data, function(index, venue) {
return $.ajax({
url: "https://api.foursquare.com/v2/venues/"+venue.id+"?"+$this.settings.key,
dataType: 'json',
success: function(res, req) {
data[index].details = detail = res.response.venue;
}
});
});
}
})
).then(function(data) {
var results = data.response.venues;
console.log(JSON.stringify(results));
});
Any help will be much appreciated, thanks!
Use done()
var request1 = $.get(...);
var request2 = $.get(...);
$.when(request1 , request2 ).done(function() {
// when both are completed
});
Check out the async Javascript library. Pass an array of venue IDs as the first argument into async.each and that should get you started. async.waterfall can also help you handle the case where you need to pass data from one asynchronous function to the next.
Related
I am working on modifying a web application built by someone else a few years ago. In it, he built an API function in JS which when called, will pull data from SharePoint. I am adding a feature to the application, and will need to do another API call to retrieve some different data. So far, I haven't been able to figure out how to modify the code so that it waits for the ajax call to complete. All of the research that I have done indicates that I should be using a callback to accomplish this, but I am not sure how to implement it properly.
The existing code looks like this:
API = function(apiFunction, dataToPost, successCallback) {
var baseApiUrl = '/SomeWebApp/API/';
var apiUrl = baseApiUrl + apiFunction;
$.ajax({
url: apiUrl,
data: JSON.stringify(dataToPost),
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function(data) { return data; },
success: successCallback,
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert('Error calling webservice: ' + apiFunction);
}
});
}
And the call to the API is:
API('Lists.asmx/GetStuff', dataToPost, function(data) {
var options = [];
$.each(data.d, function(index, value) {
options.push(new Category(value.Field, value.AnotherField, value.YetAnotherField));
});
var viewModel = new ViewModel(options);
ko.applyBindings(viewModel);
});
What I need to do is perform the second API call to retrieve the rest of the data, and then create the view model, passing it both sets of data.
What I've tried:
Moving options outside of the callback function, but it seems that because it is asynchronous, the script isn't waiting for the data to be returned. If it did work, I could move ko.ApplyBindings outside of the callback function, and just create the new view model with both sets of data
Assigning the API call to a variable, and having the callback function return options. For example:
var x = API('Lists.asmx/GetStuff', dataToPost, function(data) {
var options = [];
$.each(data.d, function(index, value) {
options.push(new Category(value.Field, value.AnotherField, value.YetAnotherField));
});
return options;
});
What would be the best way to modify the code to accomplish this? Should I create a wrapper function that includes the API function as a callback? How would I put that together?
The quick and dirty solution is to put the second API call within the callback function of the first API call. Return statements really don't do anything in an async function unless it's returning a "promise" (see option 2).
API('Lists.asmx/GetStuff', dataToPost, function(data) {
var options = [];
$.each(data.d, function(index, value) {
options.push(new Category(value.Field, value.AnotherField, value.YetAnotherField));
});
API('Lists/asmx/GetStuff2', secondDataToPost, function(data2){
var viewModel = new ViewModel(options, data2);
ko.applyBindings(viewModel);
});
});
Option 2 - since your API function is already using jQuery to handle the ajax you can change it to return the result of the ajax call, a type of deferred object, on which you can call .done to attach a callback method instead. jquery-deferred-and-promise walkthrough
API = function(apiFunction, dataToPost, successCallback) {
var baseApiUrl = '/SomeWebApp/API/';
var apiUrl = baseApiUrl + apiFunction;
return $.ajax({
...
});
}
The returned deferred object can be used similarly to the passed in callback by using the .done method on the object.
API('Lists.asmx/GetStuff', dataToPost).done(function(data) {
callback stuff...
});
This is a little more flexible and can let you do chaining and simultaneous execution like the following where both api calls get sent at the same time instead of having to wait for the response from the first call before sending the second one.
$.when(
API('Lists.asmx/GetStuff', dataToPost),
API('Lists.asmx/GetStuff2', dataToPost2)
).done(function(data1, data2) {
var options = [];
$.each(data.d, function(index, value) {
options.push(new Category(value.Field, value.AnotherField, value.YetAnotherField));
});
var viewModel = new ViewModel(options, data2);
ko.applyBindings(viewModel);
});
I have this code, it does an AJAX call to Wikipedia, asking for results of a given query (var searchText):
function main() {
$(".btn").click(function() {
$("#iframe").attr('src', 'https://en.wikipedia.org/wiki/Special:Random');
$(".embed-container").css('visibility', 'visible');
});
function wikiAjax (searchURL) {
return $.ajax({
url: searchURL,
jsonp: "callback",
dataType: 'jsonp',
xhrFields: {
withCredentials: true
}
});
}
$(".search-form").submit(function() {
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.done(function(data) {
console.log(data);
}).fail(function(err) {
alert("The call has been rejected");
});
});
}
$(document).ready(main);
But it returns me a strange object:
Could someone please help me?
you've the right response from Wikipedia, check your query parameters, specially this one
var searchText = $('#search').val();
which value you are testing with, if you entered something like "2sasd23sda" you'll get this object response.
The Ajax call needs to have 3 parameters. There is JSON data in the 3rd param. Try it with this jsfiddle.
wikiResponse.done(function(error, success, data) {
console.log(data.responseJSON.query.pages);
})
This is the correct response for a query that has no matches. the issue is most likely the search value you are appending.
Below are two result sets, one using a term that yields no response the other using Test.
Response with no results:
No Results
Response with results:
Results
I am trying to create a database handler class in javascript. I would like to call the class by simply using:
var databaseHandler = new DatabaseHandler();
result = databaseHandler.getResult("SELECT * FROM login");
I have created the class and used a callback for the ajax function (so as to wait for the ajax result to be returned). But all I am still receiving "undefined" as my result. If I use console.log(a) inside of the onComplete function, I get an array of the intended results.
(function(window){
//Database class
function DatabaseHandler(){
//Query
this.query = function(query, whenDone){
request = $.ajax({
url: "../optiMizeDashboards/php/DatabaseQuery.php",
type: "POST",
data: {query : query},
dataType: "JSON"
});
request.done(function(output) {
whenDone(output);
});
request.fail(function(jqXHR, textStatus) {
console.log(textStatus);
});
};
//Get result
this.getResult = function(query){
this.query(query, this.onComplete);
};
//Ajax callback
this.onComplete = function(a){
return a;
};
}
//Make available to global scope
window.DatabaseHandler = DatabaseHandler;
}(window))
My question is: Is this something to do with the variable scope, or the way that ajax works? I have read all the answers explaining that ajax is ASYNC and I thought I had handled that by using a callback function "onComplete"
Any help on this topic would be greatly appreciated!
You will not be able to return result immediately from calling getResult because underlying jQuery POST request is Asynchronous, instead you need to be passing a callback function which eventually will receive a result from server.
something like that:
(function(window){
//Database class
function DatabaseHandler(){
//Query
this.query = function(query, whenDone){
request = $.ajax({
url: "../optiMizeDashboards/php/DatabaseQuery.php",
type: "POST",
data: {query : query},
dataType: "JSON"
});
request.done(function(output) {
whenDone(output);
});
request.fail(function(jqXHR, textStatus) {
console.log(textStatus);
});
};
//Get result
this.getResult = function(query, callback){
this.query(query, callback);
};
}
//Make available to global scope
window.DatabaseHandler = DatabaseHandler;
}(window))
// then use it like so
var databaseHandler = new DatabaseHandler();
result = databaseHandler.getResult("SELECT * FROM login", function(data) {
//do something with data
});
PS: exposing direct SQL access to the databse on the client is very dangerous though, and I would not recommend doing that
Guys here the first script is designed to take static .json files to display certain content and animate them. The code snippet is
var self = this;
$.getJSON('data/post_'+ index +'.json', function(d){
self.postCache[index] = d;
callback(d)
but I want to modify it to so it could take data from database. I got the data in the same format as it was in static json files and my question is how can I pass that data to this script so that it work as it should.
I am sending request using ajax
$(function ()
{
$.ajax({
url: 'api.php',
data: "<?php echo $data?>",
dataType: 'json',
success: function(data)
{
//I really dont know what to write here :(
}
});
});
and the api.php file is getting data from database and I an encoding the data to json using json_encode
var self = this;
$.post('api.php',
{"post_id": index},
success: function(d)
{
self.postCache[index] = d;
callback(d);
});
see http://api.jquery.com/jquery.post/
In api.php do a SQL query where the post_id = $_POST['post_id'] then echo json_encode($database_row);
$.getJSON just calls $.ajax with some predefined values automatically set for you. This means, since you said the data is the same, that you can do exactly the same as you were doing previously.
Keep a reference to this
Make your async call
in the success function, save your reference and execute your callback
var self = this;
$.ajax({
url: 'api.php',
data: "<?php echo $data?>",
dataType: 'json',
success: function(data)
{
self.postCache[index] = data;
callback(data);
}
});
I know it sounds like something that's been asked before, but for all my hunting, I can't find anything matching what I'm looking for.
I'm working on a project that's rather heavily based on Ajax. I'm using jQuery, but even with its beautifully streamlined code, it's still messy when I've got it to the point that the code is exactly the same, except for one single command passed through the data field.
So I tried setting it up inside a handler function, like so:
function _call(task, opts, async) {
if(typeof async !== "boolean") { async = true; }
opts = $.extend({}, opts, options);
$.ajax({
url: "myphpfile.php",
dataType:"JSON",
type:"POST",
async:async,
data: { task: task, opts: opts }
}).done(function(data) { return data; });
}
For those who read through, you'll notice that there's a var,
options, that hasn't been defined in the example. It has actually
been assigned, it's just been omitted for clarity purposes.
I came to realize that this doesn't work, as even when it's set to async: false, the code still continues after the call of _call(...), therefore not getting the results in time. I've tried a few different variations, including passing an anonymous function to the handler and then using that as the .done() function, but it wouldn't interact with outside variables, defeating the purpose.
All I'm looking for is a system that will let me use it something like this:
var returnedData = _call("thisismytask");
var returnedDataWithOptions = _call("thisisanothertask", {'option': 'option1'});
I really hope this is possible. I'm sure it would be, as the main purpose of functions is to remove the need for unnecessarily repeated code.
Thanks. :)
You could do this:
function _call(task, opts) {
opts = $.extend({}, opts, options);
return $.ajax({
url: "myphpfile.php",
dataType:"JSON",
type:"POST",
data: { task: task, opts: opts }
});
}
It removes the need for passing a callback into _call, but functions just the same.
_call("thisisanothertask", {'option': 'option1'}).then(function(data) {
// function body here
});
you are probably best doing this
function _call(task, opts, callback) {
opts = $.extend({}, opts, options);
$.ajax({
url: "myphpfile.php",
dataType:"JSON",
type:"POST",
data: { task: task, opts: opts }
}).done(function(data) { callback(data); });
}
use like this
_call("thisisanothertask", {'option': 'option1'}, function(data) {
//do things with data
});
You cant really do this, as _call cant return straight away as it may take a while to get a response and even if you could it could lock your browser which is not good.
var returnedData = _call("thisismytask");
var returnedDataWithOptions = _call("thisisanothertask", {'option': 'option1'});
you need to use it like this:
_call("thisismytask", null, function(returnedData) {
//use returnData
});
_call("thisisanothertask", {'option': 'option1'}, function(returnedDataWithOptions) {
//use returnedDataWithOptions
});
If you needed the result of thisismytask before thisisanothertask you would have to do:
_call("thisismytask", null, function(returnedData) {
_call("thisisanothertask", {'option': 'option1'}, function(returnedDataWithOptions) {
//use returnData
//use returnedDataWithOptions
});
});
You should be using callbacks. You also shouldn't be using async: false as this will block the UI thread in browser. You can use jQuery.when() to sync your various tasks. First change your method like this:
function _call(task, opts) {
opts = $.extend({}, opts, options);
return $.ajax({
url: "myphpfile.php",
dataType:"JSON",
type:"POST",
data: { task: task, opts: opts }
});
}
Now you can call it like this:
$.when(
_call("thisismytask"),
_call("thisisanothertask", {'option': 'option1'})
).done(function(firstCallResults, secondCallResults) {
//*CallResults is an array with the following structure: [data, statusText, jqXHR]
var returnedData = firstCallResults[0];
var returnedDataWithOptions = secondCallResults[0];
...
});
This way you keep all the benefits of AJAX asynchrounous nature (those tasks will run in parallel unless server doesn't support it) and get your results back together when they are all available.
I found a solution. #Slavo pointed it out to me.
https://stackoverflow.com/a/6685294/563460
As you're making a synchronous request, that should be
function getRemote() {
return $.ajax({
type: "GET",
url: remote_url,
async: false,
}).responseText; }
Example - http://api.jquery.com/jQuery.ajax/#example-3
Now I just have to decode from text to proper JSON. Thank you everyone. :)
Use jQuery's syntax -
its worked for me,
$.ajaxSetup({async: false});