Ajax made Simple Part 7: Use JSONP to get a stock quote

Working with Ajax, we have run into the Same Origin Policy over and over again. In this post, we’ll show you another way to get around it.

The Same Origin Policy restricts you from loading files from a server not your own. There is an exception: JavaScript (.js) files are allowed.

There are sites on the web where you can request information and have it passed back in JSONP format. The “P” stands for padding: JSONP is JSON with padding. The results are returned as a function call, with the results as parameters. That function can then be called in your program.


Let’s use this to get a stock quote from Yahoo. There are 3 parts to this: first, we have to make the request. Next, we handle the return. Finally, we execute the function.

1. Make the request

  
 Dim YQI, URL, callback
 YQI = escape("select * from yahoo.finance.quotes where symbol in ('AAPL','GOOG','MSFT')")
 callback="requestComplete"
 URL = "http://query.yahooapis.com/v1/public/yql?q=" & YQI & _
       "&format=json&env=http://datatables.org/alltables.env&callback=" & callback
 loadScript(URL)

Yahoo! has a very powerful API to look up all kinds of data. To make it easier, they have set up an interface using SQL like statements called YQI. In our code above, we start by creating our YQI request. The escape() function translates special characters and spaces so they can be sent in our Ajax call.

URL is then composed of our YQI request with the rest of the boilerplate that is needed. The most interesting part is the &callback part. It names the function that the return values will be wrapped in.

Having prepared everything, we can inject the script.

2. Inject the script

Yahoo! is going to return some code: it will be a call to the function we specified in callback, with the parameters all filled in. The following code will insert the code returned by Yahoo! into our program and execute it:

Function loadScript(URL)
  Dim head, script
  head=document.getElementsByTagName("head")[0]
  script=document.createElement("script")
  script.src=URL
  script.async=True
  head.appendChild(script)
End Function

We do the usual checking to see if the call is complete. If it is, we will have gotten a text string back that looks something like this:

requestComplete({"query":
  {"count":3,"created":"2012-03-20T11:34:00Z","lang":"en-US","results":
     {"quote":...);

This is a valid function call, so when it is run, the function is executed.

3. Execute the function

The Eval() function causes requestComplete() to be called.

Function requestComplete(data)
  Dim quotes, i
  quotes=data.query.results.quote
  TextArea1.value=""
  For i=0 To Len(quotes)-1
    TextArea1.value=TextArea1.value+quotes[i].symbol & _
                    ": " & quotes[i].Ask & vbCRLF
  Next
End Function

The data that comes back is a fairly complex structure with a lot of data in it. You can copy it to the NotePad to see everything that is there. For now, we are just interested in the asking price of the stock. The results are returned in an array, with one element per stock.

Closing points

There are many web services that work in a similar fashion. One of the tip offs is if the calling string has an &callback argument. If it does, it probably can be used with this method.

Some of these services are free or limited, while others require an API key that you must obtain from the service.

Some places to go for services:

Got more? Let us know at support@nsbasic.com.