Using jQuery's jsonp in a module

Coming up to speed on front end development with Javascript is getting to be more of a challenge than ever.

Recently I actively watched Wes Bos’s excellent free React/Redux tutorial (active means I typed in all the code along the way and made it run).

Then I created a demo of my own using a couple API’s to demonstrate using Promises to do async actions.

One of those API’s is freely available for anyone to use (https://www.googleapis.com/youtube/v3/search), and must have a CORS policy allowing this, as fetch can be used to retrieve information asynchronously.

But the other (https://suggestqueries.google.com/complete/search?output=youtube&ds=yt&q=) is apparently mainly for Google’s internal use and does not have a CORS policy allowing the use of fetch.

It does however support JSONP, a somewhat insecure way around the Same Origin Policy. So I decided to use JSONP for this.

There are many Javascript libraries for using JSONP, and I eventually used an npm module: ‘jsonp-es6’, but to get it working for the first time I fell back on jQuery. This code is

import store from '../store';
import { newSuggestions } from '../actions/actionCreators';

var BASE_URL='http://suggestqueries.google.com/complete/search?output=youtube&jsonp=datafn&ds=yt&q=';

var callback = function(data) {
  var suggestions = data[1].map(elem => elem[0]);
  console.log("  suggestions=");
  console.log(suggestions);
  store.dispatch(newSuggestions(suggestions));
}

function fetchSuggestions(text) {
  $.getJSON("http://suggestqueries.google.com/complete/search?callback=?",
    {
      "hl": "en", // Language
      "ds": "yt", // Restrict lookup to youtube
      "jsonp": "callback", // jsonp callback function name
      "q": text, // query term
      "client": "youtube" // force youtube style response, i.e. jsonp
    }
  );
}

export default fetchSuggestions;

This code is in a webpack project module. When fetchSuggestions is invoked, the following error is produced in Chrome: Uncaught ReferenceError: callback is not defined.

Why does jQuery not bind jsonp to the local ‘callback’ function? Because jsonp can only be bound to a global variable, like this:

window.callback = function(data) {

This makes the callback variable global, so care must now be taken that it not collide with another global variable. If we use jsonp elsewhere we must pick a different name.

Replacing jQuery with the ‘jsonp-es6’ module eliminates all such worries:

import jsonp from 'jsonp-es6';
import store from '../store';
import { newSuggestions } from '../actions/actionCreators';

var BASE_URL='https://suggestqueries.google.com/complete/search?output=youtube&ds=yt&q=';

function fetchSuggestions(text) {
  jsonp(BASE_URL + text)
    .then((result) => {
      var suggestions = result[1].map(elem => elem[0]);
      //console.log("  suggestions=");
      //console.log(suggestions);
      store.dispatch(newSuggestions(suggestions));
    });
}

export default fetchSuggestions;

jsonp now returns a promise, which when resolved invokes .then. Much better.

--> Comments
comments powered by Disqus