답변:
function foo(data)
{
// do stuff with JSON
}
var script = document.createElement('script');
script.src = '//example.com/path/to/jsonp?callback=foo'
document.getElementsByTagName('head')[0].appendChild(script);
// or document.head.appendChild(script) in modern browsers
foo(payload_of_json_data)
. 스크립트 태그에로드 될 때 이미 페이로드가있는 foo 함수를 자바 스크립트 객체로 호출하고 파싱이 필요하지 않다는 생각입니다.
간단한 예제 (onSuccess 및 onTimeout 지원 포함). 필요한 경우 URL 내에서 콜백 이름을 전달해야합니다.
var $jsonp = (function(){
var that = {};
that.send = function(src, options) {
var callback_name = options.callbackName || 'callback',
on_success = options.onSuccess || function(){},
on_timeout = options.onTimeout || function(){},
timeout = options.timeout || 10; // sec
var timeout_trigger = window.setTimeout(function(){
window[callback_name] = function(){};
on_timeout();
}, timeout * 1000);
window[callback_name] = function(data){
window.clearTimeout(timeout_trigger);
on_success(data);
}
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = src;
document.getElementsByTagName('head')[0].appendChild(script);
}
return that;
})();
샘플 사용법 :
$jsonp.send('some_url?callback=handleStuff', {
callbackName: 'handleStuff',
onSuccess: function(json){
console.log('success!', json);
},
onTimeout: function(){
console.log('timeout!');
},
timeout: 5
});
GitHub : https://github.com/sobstel/jsonp.js/blob/master/jsonp.js
JSONP 란 무엇입니까?
jsonp에서 기억해야 할 중요한 점은 실제로 프로토콜이나 데이터 유형이 아니라는 것입니다. 즉석 에서 스크립트 를 로드 하고 페이지에 도입 된 스크립트를 처리 하는 방법입니다 . JSONP의 정신에서 이것은 서버에서 클라이언트 애플리케이션 / 스크립트로 새로운 javascript 객체를 도입하는 것을 의미합니다.
JSONP는 언제 필요합니까?
하나의 도메인이 같은 페이지에있는 다른 도메인의 데이터를 비동기 적으로 액세스 / 처리하도록 허용하는 한 가지 방법입니다. 주로 XHR (ajax) 요청에서 발생하는 CORS (Cross Origin Resource Sharing) 제한을 재정의하는 데 사용됩니다. 스크립트로드에는 CORS 제한이 적용되지 않습니다.
어떻게하나요
서버에서 새로운 자바 스크립트 객체를 도입하는 것은 여러 가지 방법으로 구현할 수 있지만 가장 일반적인 방법은 서버가 필요한 객체를 전달하여 '콜백'함수의 실행을 구현하는 것입니다. 콜백 기능을 사용하면 클라이언트에 이미 설정 한 단지 기능입니다 스크립트가 이 시점에서 호출로드 스크립트 로드가에 전달 된 데이터를 처리 할 수 있습니다.
예:
누군가의 집에있는 모든 항목을 기록하는 응용 프로그램이 있습니다. 내 응용 프로그램이 설정되었으며 이제 주 침실에있는 모든 항목을 검색하려고합니다.
내 응용 프로그램은에 app.home.com
있습니다. 데이터를로드하는 데 필요한 API가 켜져 api.home.com
있습니다.
서버가이를 허용하도록 명시 적으로 설정되어 있지 않으면 별도의 하위 도메인에있는 페이지에도 XHR CORS 제한이 적용되므로이 데이터를로드하는 데 ajax를 사용할 수 없습니다.
이상적으로는 x-domain XHR을 허용하도록 설정하십시오.
이상적으로는 API와 앱이 동일한 도메인에 있으므로 .NET에서 헤더를 설정할 수있는 액세스 권한이있을 수 있습니다 api.home.com
. 그렇게하면에 Access-Control-Allow-Origin:
대한 액세스 권한을 부여 하는 헤더 항목을 추가 할 수 있습니다 app.home.com
. 헤더가 다음과 같이 설정되었다고 가정하면 Access-Control-Allow-Origin: "http://app.home.com"
JSONP를 설정하는 것보다 훨씬 안전합니다. CORS가 전체 인터넷에 액세스 하지 않고도 app.home.com
원하는 모든 것을 얻을 수 있기 때문 입니다.api.home.com
api.home.com
위의 XHR 솔루션은 불가능합니다. 클라이언트 스크립트에서 JSONP 설정 : JSONP 호출을 할 때 서버의 응답을 처리하는 함수를 설정했습니다 . :
function processJSONPResponse(data) {
var dataFromServer = data;
}
서버는 다음과 같은 미니 스크립트를 반환하도록 설정 "processJSONPResponse('{"room":"main bedroom","items":["bed","chest of drawers"]}');"
되어야 //api.home.com?getdata=room&room=main_bedroom
합니다. 유사한 것이 호출 되면 그러한 문자열을 반환하도록 설계되었을 수 있습니다 .
그런 다음 클라이언트는 다음과 같이 스크립트 태그를 설정합니다.
var script = document.createElement('script');
script.src = '//api.home.com?getdata=room&room=main_bedroom';
document.querySelector('head').appendChild(script);
이것은 스크립트를로드 window.processJSONPResponse()
하고 서버에 의해 쓰여진 / 에코 / 인쇄 된대로 즉시 호출 합니다. 함수에 매개 변수로 전달 된 데이터는 이제 dataFromServer
로컬 변수에 저장되며 필요한 모든 작업을 수행 할 수 있습니다.
정리
클라이언트가 데이터를 가지면, 즉. 스크립트가 DOM에 추가 된 직후 DOM에서 스크립트 요소를 제거 할 수 있습니다.
script.parentNode.removeChild(script);
SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data
. : 데이터에 작은 따옴표를 추가 한 후, 다 잘, 그래서 일"processJSONPResponse('{"room":"main bedroom","items":["bed","chest of drawers"]}');"
내 이해는 실제로 JSONP와 함께 스크립트 태그를 사용한다는 것입니다.
첫 번째 단계는 JSON을 처리 할 함수를 만드는 것입니다.
function hooray(json) {
// dealin wit teh jsonz
}
이 기능이 글로벌 수준에서 액세스 가능한지 확인하십시오.
다음으로, 스크립트 요소를 DOM에 추가합니다.
var script = document.createElement('script');
script.src = 'http://domain.com/?function=hooray';
document.body.appendChild(script);
스크립트는 API 공급자가 빌드 한 JavaScript를로드하고 실행합니다.
eval
또는 parse
아무것도 나. 브라우저가 바로 실행할 수있는 JavaScript를 얻어야합니다.
아래와 같이 jsonp를 사용하는 방법 :
function jsonp(uri) {
return new Promise(function(resolve, reject) {
var id = '_' + Math.round(10000 * Math.random());
var callbackName = 'jsonp_callback_' + id;
window[callbackName] = function(data) {
delete window[callbackName];
var ele = document.getElementById(id);
ele.parentNode.removeChild(ele);
resolve(data);
}
var src = uri + '&callback=' + callbackName;
var script = document.createElement('script');
script.src = src;
script.id = id;
script.addEventListener('error', reject);
(document.getElementsByTagName('head')[0] || document.body || document.documentElement).appendChild(script)
});
}
그런 다음 다음과 같이 'jsonp'메소드를 사용하십시오.
jsonp('http://xxx/cors').then(function(data){
console.log(data);
});
참고:
JsonP를 사용한 JavaScript XMLHttpRequest
http://www.w3ctech.com/topic/721(Promise 사용 방법에 대해 이야기)
https://github.com/robertodecurnex/J50Npi/blob/master/J50Npi.js 를 수행하는 순수한 자바 스크립트 라이브러리가 있습니다.
그것을 살펴보고 코드를 사용하거나 이해하는 데 도움이 필요하면 알려주십시오.
Btw, 여기에 간단한 사용 예가 있습니다. http://robertodecurnex.github.com/J50Npi/
/**
* Loads data asynchronously via JSONP.
*/
const load = (() => {
let index = 0;
const timeout = 5000;
return url => new Promise((resolve, reject) => {
const callback = '__callback' + index++;
const timeoutID = window.setTimeout(() => {
reject(new Error('Request timeout.'));
}, timeout);
window[callback] = response => {
window.clearTimeout(timeoutID);
resolve(response.data);
};
const script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = url + (url.indexOf('?') === -1 ? '?' : '&') + 'callback=' + callback;
document.getElementsByTagName('head')[0].appendChild(script);
});
})();
const data = await load('http://api.github.com/orgs/kriasoft');
window[callback] = null
함수가 가비지 수집되도록 허용하는 것을 잊지 마십시오 .
가능한 한 간단하게이를 처리하기 위해 라이브러리를 작성했습니다. 외부로 만들 필요가 없으며 하나의 기능입니다. 다른 옵션과 달리이 스크립트는 자체적으로 정리되며 런타임시 추가 요청을 만들기 위해 일반화됩니다.
https://github.com/Fresheyeball/micro-jsonp
function jsonp(url, key, callback) {
var appendParam = function(url, key, param){
return url
+ (url.indexOf("?") > 0 ? "&" : "?")
+ key + "=" + param;
},
createScript = function(url, callback){
var doc = document,
head = doc.head,
script = doc.createElement("script");
script
.setAttribute("src", url);
head
.appendChild(script);
callback(function(){
setTimeout(function(){
head
.removeChild(script);
}, 0);
});
},
q =
"q" + Math.round(Math.random() * Date.now());
createScript(
appendParam(url, key, q), function(remove){
window[q] =
function(json){
window[q] = undefined;
remove();
callback(json);
};
});
}
JQuery없이 전화를 걸 JavaScript
려면 아래 예제를 찾으십시오 JSONP
.
또한 참조를 GitHub
위해 내 저장소를 참조 할 수 있습니다 .
https://github.com/shedagemayur/JavaScriptCode/tree/master/jsonp
window.onload = function(){
var callbackMethod = 'callback_' + new Date().getTime();
var script = document.createElement('script');
script.src = 'https://jsonplaceholder.typicode.com/users/1?callback='+callbackMethod;
document.body.appendChild(script);
window[callbackMethod] = function(data){
delete window[callbackMethod];
document.body.removeChild(script);
console.log(data);
}
}
/**
* Get JSONP data for cross-domain AJAX requests
* @private
* @link http://cameronspear.com/blog/exactly-what-is-jsonp/
* @param {String} url The URL of the JSON request
* @param {String} callback The name of the callback to run on load
*/
var loadJSONP = function ( url, callback ) {
// Create script with url and callback (if specified)
var ref = window.document.getElementsByTagName( 'script' )[ 0 ];
var script = window.document.createElement( 'script' );
script.src = url + (url.indexOf( '?' ) + 1 ? '&' : '?') + 'callback=' + callback;
// Insert script tag into the DOM (append to <head>)
ref.parentNode.insertBefore( script, ref );
// After the script is loaded (and executed), remove it
script.onload = function () {
this.remove();
};
};
/**
* Example
*/
// Function to run on success
var logAPI = function ( data ) {
console.log( data );
}
// Run request
loadJSONP( 'http://api.petfinder.com/shelter.getPets?format=json&key=12345&shelter=AA11', 'logAPI' );
window.document.getElementsByTagName('script')[0];
안돼 document.body.appendChild(…)
?
logAPI
로 설정 null
가비지 컬렉션은 그것을 수행 할 수 있도록 할 때?
NPM과 함께 ES6를 사용하는 경우 노드 모듈 "fetch-jsonp"를 사용해 볼 수 있습니다. Fetch API 일반 XHR 호출로 JsonP 호출을 지원합니다.
전제 조건 : isomorphic-fetch
스택에서 노드 모듈 을 사용해야합니다 .
ES6 버전의 sobstel의 멋진 대답을 붙여 넣으십시오.
send(someUrl + 'error?d=' + encodeURI(JSON.stringify(json)) + '&callback=c', 'c', 5)
.then((json) => console.log(json))
.catch((err) => console.log(err))
function send(url, callback, timeout) {
return new Promise((resolve, reject) => {
let script = document.createElement('script')
let timeout_trigger = window.setTimeout(() => {
window[callback] = () => {}
script.parentNode.removeChild(script)
reject('No response')
}, timeout * 1000)
window[callback] = (data) => {
window.clearTimeout(timeout_trigger)
script.parentNode.removeChild(script)
resolve(data)
}
script.type = 'text/javascript'
script.async = true
script.src = url
document.getElementsByTagName('head')[0].appendChild(script)
})
}