JSONP Callback is Undefined - javascript

I'm a NOOB and I see that other users have encountered a similar problem, but after many hours of frustration, I cannot get a JSONP callback function to work.
I'm trying to extract the "woeid" information from Yahoo geo.places so I can use it to specify the location to obtain weather data. I receive input (such as a zip code) from the "location" id in a form and submit it to Yahoo.
The code is returning an XMLHttpRequest object, which I can read by looking at xhr.responseText in the console, but I can't extract the JSON object that is being passed to the callback function by the server.
I know I must be making a simple error, however I can't figure out what it is. I'm trying to do this through Javascript prior to learning how to retrieve the data using the $.ajax method in jQuery.
Can you tell me where the error is? Here is my code:
// an XMLTHttpRequest
var xhr = null;
/*
* void
* getWoeid()
* gets WOEID from Yahoo geo.places to use in request
* for weather data
*
*/
function getWoeid() {
// instantiate XMLHttpRequest object
try {
xhr = new XMLHttpRequest();
}
catch (e) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
// handle old browsers
if (xhr == null) {
alert("Ajax not supported by your browser!");
return;
}
// construct URL
var userinput = document.getElementById("location").value;
var data = encodeURIComponent("select * from" +
" geo.places where text =" + userinput);
var url = "http://query.yahooapis.com/v1/public/yql?q=" + data + "&format=json& callback=callback";
// get data
xhr.onreadystatechange = handler;
xhr.open("GET", url, true);
xhr.send(null);
}
// callback function
function callback(response) {
woeid = response;
}
/*
* void
* handler()
*
* Handles the Ajax response
*/
function handler() {
// only handle loaded requests
if (xhr.readyState == 4) {
// display response if possible
if (xhr.status == 200) {
var location = woeid;
}
else
alert("Error with Ajax call");
}
}

You can't use an XHR object to request a JSONP result, because of the same origin policy. Also, even if you would make a request locally, using an XHR object to make the request would mean that the callback function would not be called, you would just get the code for calling it in the response.
To get make a JSONP request, you use a script tag:
var script = document.createElement('script');
script.src = url;
document.head.appendChild(script);

Related

I can't get a response from the server

I followed some guides on how to send json objects to the server(written using node.js) and it doesn't work, I have no idea what is wrong. I know that my server works fine since I tested it on postman so it's my js code that's the problem, all the tutorials I see follow a similar XMLHttpRequest format.
this is my code
var ing = new Ingredient(name, date, qty, rp);
var url = "http://localhost:8081/addIngredient";
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
//Send the proper header information along with the request
// application/json is sending json format data
xhr.setRequestHeader("Content-type", "application/json");
// Create a state change callback
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// Print received data from server
result.innerHTML = this.responseText;
}
};
// Converting JSON data to string
var data = JSON.stringify(ing);
document.write(data);
// Sending data with the request
xhr.send(data);
I used document.write to check where the code stops working but everything passes (since the document.write prints something), I suspect that there is something wrong/missing from xhr.send(data) but I can't tell what. Finally, nothing gets printed from the callback.
It's better to use onload instead of onreadystatechange
xhr.onload = function() {
if (xhr.status == 200) {
console.log(`Response length = ${xhr.response.length}`);
// store xhr.response here somewhere
}
};

How to have javascript read a JSON URL

I want my javascript file to search a URL that is a JSON and grab specific contents from the page. This is the URL
And I want to grab the averageratingscore_rf.
I've even tried this :
var getJSON = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status === 200) {
callback(null, xhr.response);
} else {
callback(status, xhr.response);
}
};
xhr.send();
};
getJSON('https://search.mtvnservices.com/typeahead/suggest/?solrformat=true&rows=20&callback=noCB&q=burgos+AND+schoolid_s%3A1262&defType=edismax&qf=teacherfirstname_t%5E2000+teacherlastname_t%5E2000+teacherfullname_t%5E2000+autosuggest&bf=pow(total_number_of_ratings_i%2C2.1)&sort=total_number_of_ratings_i+desc&siteName=rmp&rows=20&start=0&fl=pk_id+teacherfirstname_t+teacherlastname_t+total_number_of_ratings_i+averageratingscore_rf+schoolid_s&fq=',
function(err, data) {
if (err !== null) {
alert('Something went wrong: ' + err);
} else {
console.log(data.response.docs.averageratingscore_rf);
}
});
But this doesn't work.
It's not a json, it's jsonp response.
JSONP requests perfomed by pass callback name and load this url into DOM script tag.
just don't try ajax+eval, anyway CORS restricts ajax here
Also, data.response.docs is an array, you should iterate it to access averageratingscore_rf
let cb = 'mycallback';
let url = `https://search.mtvnservices.com/typeahead/suggest/?solrformat=true&rows=20&callback=${cb}&q=burgos+AND+schoolid_s%3A1262&defType=edismax&qf=teacherfirstname_t%5E2000+teacherlastname_t%5E2000+teacherfullname_t%5E2000+autosuggest&bf=pow(total_number_of_ratings_i%2C2.1)&sort=total_number_of_ratings_i+desc&siteName=rmp&rows=20&start=0&fl=pk_id+teacherfirstname_t+teacherlastname_t+total_number_of_ratings_i+averageratingscore_rf+schoolid_s&fq=`
function mycallback(data) {
let res = data.response.docs.map(doc => doc.averageratingscore_rf)
console.log('averageratingscore_rf of docs:', res);
}
let script = document.createElement('script');
script.src = url;
document.body.appendChild(script)
Your URL is for JSONP, removing the callback argument returns JSON. (Remove callback=noCB)
Since you tagged google-chrome-extension Same Origin Policy may not apply but keep in mind Cross Origin Resource Sharing may need to be enabled.
... or you could handle the JSONP
Your URL isn't giving back pure JSON. There's a noCB() function wrapping it. That's probably why it's not being read.
Here's what I saw when I opened the URL:
noCB({ "responseHeader":{ "status":0, "QTime":1}, "response":{"numFound":1,"start":0,"docs":[ { "teacherlastname_t":"Burgos", "pk_id":282380, "schoolid_s":"1262", "averageratingscore_rf":2.47, "total_number_of_ratings_i":125, "teacherfirstname_t":"Fernando"}] }, "spellcheck":{ "suggestions":[]}} );
You may be able to execute that method, but if you only want the json, you can either strip out the "noCB(" and ");" at the beginning or the end when you get it, or strip it out at the server.

How can I convert this AJAX request function (raw Javascript) to use POST instead of GET?

I was looking for AJAX in pure JavaScript (without jQuery) for learning purposes and came across this video, along with the code (shown below) on how to make one. However, it's geared towards GET method and I'm not sure how to tweak it to accept additional parameters so that the function can be used for either POST or GET depending on my specified parameters. For example, the lines xhr.open('GET', url, true); and xhr.send(''); both are GET-specific (all other lines in the function are the same for both GET and POST methods)--I want to be able to be able to specify whether to use POST or GET as a parameter for function load for xhr.open and a string such as "username="+username+"&password="+password for function load for xhr.send('');
For example, the function below is for GET and is used like this load('emails.php', function(xhr) {...}. I want the function to be used like this: load('emails.php', 'POST', '"username="+username+"&password="+password' function(xhr) {...}` for POST andload('emails.php', 'GET', '', function(xhr) {...}`
The function for AJAX for GET:
function load(url, callback) {
var xhr;
if(typeof XMLHttpRequest !== 'undefined') xhr = new XMLHttpRequest();
else {
var versions = ["Microsoft.XmlHttp",
"MSXML2.XmlHttp",
"MSXML2.XmlHttp.3.0",
"MSXML2.XmlHttp.4.0",
"MSXML2.XmlHttp.5.0"];
for(var i = 0, len = versions.length; i < len; i++) {
try {
xhr = new ActiveXObject(versions[i]);
break;
}
catch(e){}
} // end for
}
xhr.onreadystatechange = function() {
if((xhr.readyState < 4) || xhr.status !== 200) return;
callback(xhr);
};
xhr.open('GET', url, true);
xhr.send('');
}
Right now the request body is set to null and ignored since you are making a GET request. You should just be able to put whatever you want sent in the body of the POST request inside of the send method:
xhr.open('POST', url, true);
xhr.send(JSON.stringify(someJsonHere));
Check out the documentation for the xhr.send method here:
Here is also a link to a more thorough guide on using XMLHttpRequests; at the bottom it has a section specific to sending data.

Normal redirect or preload

So on the net I've come across a several ways to preload / redirect a webpage.
Now's the question is this the proper way to handle a redirect with preload (Load the next page async while still showing the current page)
$.get("page.php", function (data) {
document.open();
document.write(data);
document.close();
window.history.pushState("Title", "Title", "/page.php");
$.cache = {};
}, "html");
Or should I better stay with a regular redirect?
window.location = "page.php";
The next page contains a fullscreen video and a soundtrack (audio)
Thanks.
You can use Ajax to load next page asynchronous.
Here is an example of a simple Ajax request using the GET method, written in JavaScript.
AJAX stands for Asynchronous JavaScript and XML, and for the XMLHttpRequest object to behave as AJAX, the async parameter of the open() method has to be set to true: xhr.open('get', 'send-ajax-data.php', true);
get-ajax-data.js:
// This is the client-side script.
// Initialize the Ajax request.
var xhr = new XMLHttpRequest();
xhr.open('get', 'send-ajax-data.php', true); // `true` makes the request asynchronous
// Track the state changes of the request.
xhr.onreadystatechange = function () {
var DONE = 4; // readyState 4 means the request is done.
var OK = 200; // status 200 is a successful return.
if (xhr.readyState === DONE) {
if (xhr.status === OK) {
alert(xhr.responseText); // 'This is the returned text.'
} else {
alert('Error: ' + xhr.status); // An error occurred during the request.
}
}
};
// Send the request to send-ajax-data.php
xhr.send(null);
And at the end you can use below codes to reload or redirect page data:
document.getElementById("myDiv").innerHTML = xhr.responseText;

How do i correctly format parameters passed server-side using javascript?

I cannot figure out how to get the following code working in my little demo ASP.NET application, and am hoping someone here can help.
Here is the javascript:
function checkUserName() {
var request = createRequest();
if (request == null) {
alert("Unable to create request.");
} else {
var theName = document.getElementById("username").value;
var userName = escape(theName);
var url = "Default.aspx/CheckName";
request.onreadystatechange = createStateChangeCallback(request);
request.open("GET", url, true);
request.setRequestHeader("Content-Type", "application/json");
//none of my attempts to set the 'values' parameter work
var values = //JSON.stringify({userName:"userName"}); //"{userName:'temp name'}"; //JSON.stringify({ "userName":userName });
request.send(values);
}
}
Here is the method in my *.aspx.cs class:
[WebMethod]
[ScriptMethod(UseHttpGet=true)]
public static string CheckName(string userName)
{
string s = "userName";
return s + " modified backstage";
}
When this code runs I receive this exception:
---------------------------
Message from webpage
---------------------------
{"Message":"Invalid web service call, missing value for parameter: \u0027userName\u0027.","StackTrace":" at System.Web.Script.Services.WebServiceMethodData.CallMethod(Object target, IDictionary`2 parameters)\r\n at System.Web.Script.Services.WebServiceMethodData.CallMethodFromRawParams(Object target, IDictionary`2 parameters)\r\n at System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary`2 rawParams)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.InvalidOperationException"}
---------------------------
OK
---------------------------
I started searching here, then went on to several threads on SO, trying quite a few combinations of quotation marks and key-value pairs, but nothing I've tried has worked.
When I remove the parameter from the C# method and request.send(), I get a response in my JS callback that I can work with. But as soon as I try to do something with parameters, I get the above exception. I'd like to know how to do this without using jQuery, if possible.
Thanks in advance.
FINAL VERSION
Using Alexei's advice, I ended up with the following, which works. The URL was missing the apostrophes on either end of the parameter value; this was keeping the call from going through.
function checkUserName() {
var request = createRequest();
if (request == null) {
alert("Unable to create request.");
} else {
var theName = document.getElementById("username").value;
var userName = encodeURIComponent(theName);
var url = "Default.aspx/CheckName?name='" + theName + "'";
request.onreadystatechange = createStateChangeCallback(request);
request.open("GET", url, true);
request.setRequestHeader("Content-Type", "application/json");
request.send();
}
}
request.send(values);
This won't work with a "GET". Try
request.open("POST", url, true);
http://www.w3schools.com/ajax/ajax_xmlhttprequest_send.asp
You need to:
decide whether you want GET or POST. For GET request you need all parameters to be in Url (and body to be empty), for POST you can use both. As of current code you are expecting GET, but sending POST.
properly add query parameter - name and encoded value. encodeUriComponent is JavaScript function of choice, see Build URL from Form Fields with Javascript or jquery for details
if using POST you need to properly encode parameters there too as well specify correct "content-type" header.
if sending JSON you need to decode JSON server side.
Alternatively you can use hidden form to perform POST/GET as covered in JavaScript post request like a form submit
Side note: jQuery.ajax does most of that for you and good source to look through if you want to do all yourself.
Like Alan said, use the POST method. Or pass your arguments in your URL before opening it, e.g.
var url = "Default.aspx/CheckName?userName=" + values;
EDIT : no, it's probably a bad idea since you want to send JSON, forget what I said.
If you need to go for POST, then you need to send it like this.
var values = JSON.stringify({"'userName':'"+ userName+ "'"});
And you have to change HttpGet to HttpPost
Given that your server side method asks for GET, you need:
request.open("GET", url + "?username=" + userName, true);
request.send();
The works for me:
function checkUserName() {
var request = new XMLHttpRequest();
if (request == null) {
alert("Unable to create request.");
} else {
var userName = "Shaun Luttin";
var url = '#Url.RouteUrl(new{ action="CheckName", controller="Home"})';
request.onreadystatechange = function() {
if (request.readyState == XMLHttpRequest.DONE ) {
if(request.status == 200){
document.getElementById("myDiv").innerHTML = request.responseText;
}
else if(request.status == 400) {
alert('There was an error 400')
}
else {
alert('something else other than 200 was returned')
}
}
}
request.open("GET", url + "?username=" + userName, true);
request.send();
}
}
With this on the server side:
[HttpGet]
public string CheckName(string userName)
{
return userName + " modified backstage";
}

Categories

Resources