49 lines
2.3 KiB
JavaScript
49 lines
2.3 KiB
JavaScript
var CallbackRegistry = {}; // реестр
|
||
|
||
// при успехе вызовет onSuccess, при ошибке onError
|
||
function scriptRequest(url, onSuccess, onError) {
|
||
|
||
var scriptOk = false; // флаг, что вызов прошел успешно
|
||
|
||
// сгенерировать имя JSONP-функции для запроса
|
||
var callbackName = 'cb' + String(Math.random()).slice(-6);
|
||
|
||
// укажем это имя в URL запроса
|
||
url += ~url.indexOf('?') ? '&' : '?';
|
||
url += 'callback=CallbackRegistry.'+callbackName;
|
||
|
||
// ..и создадим саму функцию в реестре
|
||
CallbackRegistry[callbackName] = function(data) {
|
||
scriptOk = true; // обработчик вызвался, указать что всё ок
|
||
delete CallbackRegistry[callbackName]; // можно очистить реестр
|
||
onSuccess(data); // и вызвать onSuccess
|
||
};
|
||
|
||
// эта функция сработает при любом результате запроса
|
||
// важно: при успешном результате - всегда после JSONP-обработчика
|
||
function checkCallback() {
|
||
if (scriptOk) return; // сработал обработчик?
|
||
delete CallbackRegistry[callbackName];
|
||
onError(url); // нет - вызвать onError
|
||
}
|
||
|
||
var script = document.createElement('script');
|
||
|
||
// в старых IE поддерживается только событие, а не onload/onerror
|
||
// в теории 'readyState=loaded' означает "скрипт загрузился",
|
||
// а 'readyState=complete' -- "скрипт выполнился", но иногда
|
||
// почему-то случается только одно из них, поэтому проверяем оба
|
||
script.onreadystatechange = function() {
|
||
if (this.readyState == 'complete' || this.readyState == 'loaded'){
|
||
this.onreadystatechange = null;
|
||
setTimeout(checkCallback, 0); // Вызвать checkCallback - после скрипта
|
||
}
|
||
}
|
||
|
||
// события script.onload/onerror срабатывают всегда после выполнения скрипта
|
||
script.onload = script.onerror = checkCallback;
|
||
script.src = url;
|
||
|
||
document.body.appendChild(script);
|
||
}
|
||
|