I just learned the
Microsoft Bing search engine API (which is actually a Live Search rebranding, also switching to “low bandwidth browsing” to be able to use documents more flexibly), and found an interesting trick to protect the code from throwing exceptions.
When you submit a JSON output format to developers, it makes sense to also give the option to pass the “callback function” parameter. In this case, it becomes possible to use your output format by simply using the script tag, without using any Ajax. Suppose, for example, that you provide an API to return the names of members of a group of Beatles, providing an end point and a parameter for setting the output format:
example.com/API/getBeatles?output=json
The returned data is in the form:
{
"members" :
[
'Paul' :{ ... more info ... },
'Ringo' :{ ... more info ... },
'John' :{ ... more info ... },
'George' :{ ... more info ... }
]
}
* This source code was highlighted with Source Code Highlighter .
This I can not use in JavaScript without feints. I will need to perform eval (or more secure
JSON.parse ) on the received data, and besides the usual Ajax, I will not be able to access data outside my domain. To make accessing JSON data easier, you can provide a callback parameter.
')
example.com/API/getBeatles?output=json&callback=eleanorRigby
With this parameter, the results are wrapped in a function call, which means that the result will already be calculated, and the user has defined a callback function to read this information.
eleanorRigby({
"members" :
[
'Paul' :{ ... more info ... },
'Ringo' :{ ... more info ... },
'John' :{ ... more info ... },
'George' :{ ... more info ... }
]
});
* This source code was highlighted with Source Code Highlighter .
If I define a function like
eleanorRigby(o){}
, the parameter
o
will be an object with the received data, and I can use them immediately.
< script >
function eleanorRigby(o){
alert(o[ 'John' ]); // will alert the information about John
}
</ script >
< script src ="http://example.com/API/getBeatles?output=json&callback=eleanorRigby" ></ script >
* This source code was highlighted with Source Code Highlighter .
But in this case, the problem arises that if the function
eleanorRigby
not defined, an exception will be thrown.
The Bing API is the first instance of the service I saw that frames its output in the form:
if ( typeof eleanorRigby == 'function' ) eleanorRigby(
{
"SearchResponse" :
{
"Version" : "2.2" ,
"Query" :
{
"SearchTerms" : "a hard day's night"
},
"Translation" :
{
"Results" :
[
{ "TranslatedTerm" : "einem harten Tag-Nacht " }
]
}
}
} /* pageview_candidate */ );
* This source code was highlighted with Source Code Highlighter .
I don’t know what the comment / * pageview_candidate * / means, and I don’t like the absence of the {} block after if, but I like the idea.
The problem in this code is only one - errors of this kind are now silently skipped, which can complicate the debugging process. It would probably be more beautiful to write a message to the console in case of an error if the callback function is not defined.
if ( typeof callback === 'function' ) {
callback(... data ... );
} else {
if ( typeof console!== 'undefined' &&
typeof console.log !== 'undefined' ){
console.log( 'Error: Callback method not defined' );
}
}
* This source code was highlighted with Source Code Highlighter .
In general, a very interesting approach!
From the translator: By the way, getting data through the script tag is often also more productive than eval and sometimes even compared to native JSON.parse. According to the link, however, there is no comparison with JSONP.