関数定義
JavaScript初心者なので改善点あればマサカリください。
jsonp_loader.js
function loadJSONP(url, params, timeout, callbackParamName) {
params = params || {};
timeout = timeout || 0;
callbackParamName = callbackParamName || 'callback';
var callbackName = 'jsonpCallback' + Math.random().toString(16).slice(2);
params[callbackParamName] = callbackName;
url += '?' + Object.keys(params).map(function (key) {
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
}).join('&');
var script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
return new Promise(function (resolve, reject) {
window[callbackName] = resolve;
script.addEventListener('error', reject);
if (timeout > 0) {
setTimeout(reject, timeout);
}
}).then(function (response) {
delete window[callbackName];
document.body.removeChild(script);
return Promise.resolve(response);
}, function (e) {
var msg = e ? 'Execution Failed' : 'Request Timeout';
delete window[callbackName];
document.body.removeChild(script);
return Promise.reject('JSONP ' + msg + ': ' + url);
});
}
最初エラーハンドリングの方法に悩んでいたのですが、onerror
属性で何とかなりました。@gaogao_9さん助言ありがとうございました。
↓
@chitokuさんによりよい方法を教えていただいたので採用しました。
↓
@Raggさんにdelete
の提案をいただきました。
↓
ついでにタイムアウトでエラーにする機能も付けました。
↓
@think49さんにObject.keys
の提案をいただきました。
使用例
面倒なのでHTML5の最省略形で書いてます。
index.html
<!DOCTYPE html>
<title>example</title>
<script src="jsonp_loader.js"></script>
<script>
// はてなブックマークの総数を並列に取得してきて
// 全部終わったらコンソールに表示するだけのコード
window.onload = function () {
var hatebuUrl = 'http://api.b.st-hatena.com/entry.counts';
var list = [
'http://www.google.com/',
'http://yahoo.co.jp/',
'http://twitter.com/',
'http://qiita.com/'
];
Promise.all(list.map(function (url) {
return loadJSONP(hatebuUrl, {url: url});
})).then(function (results) {
console.log(results); // レスポンスの配列になってます
}, function (message) {
console.error(message); // 最初の1件のエラーのみ取り扱われます
});
};
</script>
実際には、はてブAPIは50件まで一気にまとめてリクエスト出来るようなので、出来る限りそれに従った実装を採り、サーバに負荷をかけないようにしましょう。