Pull to refresh

Безопасный JSONP? Интересная особенность Bing API

JavaScript *
Translation
Original author: Chris Heilmann
Я только что изучил API нового поисковика Bing от Microsoft (который фактически является ребрендингом Live Search, также с переключением на «просмотр с малой полосой пропускания», чтобы иметь возможность использовать документы более гибко), и нашёл интересный финт для защиты кода от выброса исключений.

Когда вы представляете выходной формат JSON для разработчиков, имеет смысл также дать возможность передачи параметра «функция обратного вызова». При этом возникает возможность использования вашего выходного формата с помощью простого использования тэга script, без использования какого-либо Ajax. Предположим, к примеру, что вы предоставляете API, чтобы вернуть имена участников группы Битлз, предоставляя конечную точку и параметр для задания выходного формата:

example.com/API/getBeatles?output=json

Возвращаемые данные представлены в форме:
{
 "members":
   [
    'Paul':{ ... more info ... },
    'Ringo':{ ... more info ... },
    'John':{ ... more info ... },
    'George':{ ... more info ... }
  ]
}


* This source code was highlighted with Source Code Highlighter.

Это я не смогу использовать в JavaScript без финтов. Мне нужно будет выполнить eval (или более безопасный JSON.parse) над полученными данными, и к тому же обычным Ajax я не смогу получить доступ к данным за пределами своего домена. Чтобы сделать доступ к данным JSON более простым, Вы можете предоставить параметр обратного вызова.

example.com/API/getBeatles?output=json&callback=eleanorRigby

При наличии этого параметра результаты оборачиваются в вызов функции, что означает, что результат будет уже вычислен, и пользователь определил функцию обратного вызова для чтения данной информации.
eleanorRigby({
 "members":
   [
    'Paul':{ ... more info ... },
    'Ringo':{ ... more info ... },
    'John':{ ... more info ... },
    'George':{ ... more info ... }
  ]
});


* This source code was highlighted with Source Code Highlighter.

Если я определю функцию наподобие eleanorRigby(o){}, параметр o будет обьектом с полученными данными, и я смогу использовать их немедленно.
<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.

Но в таком случае проблема возникает, что в случае, если функция eleanorRigby не определена, будет выброшено исключение.

Bing API является первым экземпляром сервиса, который я видел, который обрамляет свой вывод в виде:
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.

Я не в курсе, что означает комментарий /* pageview_candidate */, и мне не нравится отсутствие блока {} после if, но сама идея мне нравится.

Проблема в этом коде только одна — ошибки такого рода теперь молча пропускаются, что может усложнить процесс отладки. Вероятно, более красиво было бы в случае ошибки писать сообщение в консоль, если функция обратного вызова не определена.
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.

В целом весьма интересный подход!

От переводчика: Кстати, получение данных через тэг script часто также более производительно по сравнению с eval и иногда даже по сравнению с нативным JSON.parse. По ссылке, правда, сравнения именно с JSONP нет.
Tags:
Hubs:
Total votes 35: ↑28 and ↓7 +21
Views 1.6K
Comments Comments 17