Comment faire une requête JSONP de Javascript sans JQuery?

Puis-je faire une requête JSONP multi-domaine en JavaScript sans utiliser jQuery ou autre bibliothèque externe? J'aimerais utiliser le JavaScript lui-même, puis analyser les données et en faire un objet pour pouvoir l'utiliser. Dois-je utiliser une bibliothèque externe? Sinon, comment puis-je le faire?

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 

Exemple léger (avec support pour onSuccess et onTimeout). Vous devez passer le nom de rappel dans l'URL si vous en avez besoin.

 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; })(); 

Exemple d'utilisation:

 $jsonp.send('some_url?callback=handleStuff', { callbackName: 'handleStuff', onSuccess: function(json){ console.log('success!', json); }, onTimeout: function(){ console.log('timeout!'); }, timeout: 5 }); 

Chez GitHub: https://github.com/sobstel/jsonp.js/blob/master/jsonp.js

Qu'est-ce que JSONP?

La chose importante à retenir avec jsonp est que ce n'est pas en fait un protocole ou un type de données. C'est juste une façon de charger un script à la volée et de traiter le script qui est présenté à la page. Dans l'esprit de JSONP, cela implique l'introduction d'un nouvel objet javascript du serveur dans l'application / script client.

Quand JSONP a-t-il besoin?

Il s'agit d'une méthode consistant à permettre à un domaine d'accéder / traiter les données d'un autre dans la même page de façon asyncronique. Principalement, il est utilisé pour annuler les restrictions CORS (Cross Origin Resource Sharing) qui se produiraient avec une requête XHR (ajax). Les charges de script ne sont pas soumises aux restrictions CORS.

Comment est-il fait

L'introduction d'un nouvel objet javascript à partir du serveur peut être implémentée de plusieurs façons, mais la pratique la plus courante est que le serveur implémente l'exécution d'une fonction de rappel, l'objet requis étant passé. La fonction de rappel est juste une fonction que vous avez déjà configurée sur le client que le script vous chargez les appels au point où le script est chargé pour traiter les données transmises.

Exemple:

J'ai une application qui enregistre tous les objets dans la maison de quelqu'un. Mon application est configurée et je souhaite maintenant récupérer tous les éléments dans la chambre principale.

Mon application est sur app.home.com . Les apis dont j'ai besoin pour charger des données sont sur api.home.com .

À moins que le serveur ne soit configuré explicitement pour l'autoriser, je ne peux pas utiliser ajax pour charger ces données car des pages même sur des sous-domaines distincts sont sujettes aux restrictions de XHR CORS.

Idéalement, configurez les choses pour permettre le X-domaine XHR

Idéalement, puisque l'api et l'application sont sur le même domaine, je pourrais avoir accès à la configuration des en-têtes sur api.home.com . Si je le fais, je peux ajouter un attribut Access-Control-Allow-Origin: tête donnant accès à app.home.com . En supposant que l'en-tête est configuré comme suit: Access-Control-Allow-Origin: "http://app.home.com" , c'est beaucoup plus sécurisé que la configuration de JSONP. C'est parce que app.home.com peut obtenir tout ce qu'il veut d' api.home.com sans api.home.com donnant accès à api.home.com à l'Internet entier.

La solution XHR ci-dessus n'est pas possible. Configurer JSONP Sur mon script client: J'ai configuré une fonction pour traiter la réponse du serveur lorsque je fais l' appel JSONP. :

 function processJSONPResponse(data) { var dataFromServer = data; } 

Le serveur devra être configuré pour retourner un mini script qui ressemble à "processJSONPResponse({"room":"main bedroom","items":["bed","chest of drawers"]});" Il pourrait être conçu pour renvoyer une telle chaîne si quelque chose comme //api.home.com?getdata=room&room=main_bedroom est appelé.

Ensuite, le client configure une étiquette de script en tant que telle:

 var script = document.createElement('script'); script.src = '//api.home.com?getdata=room&room=main_bedroom'; document.querySelector('head').appendChild(script); 

Cela charge le script et appelle immédiatement window.processJSONPResponse() tel qu'écrit / écho / imprimé par le serveur. Les données transmises en tant que paramètre à la fonction sont maintenant stockées dans la variable locale dataFromServer et vous pouvez faire avec elle tout ce dont vous avez besoin.

Nettoyer

Une fois que le client a les données, c'est-à-dire. Immédiatement après l'ajout du script au DOM, l'élément de script peut être retiré du DOM:

 script.parentNode.removeChild(script); 

Ma compréhension est que vous utilisez des étiquettes de script avec JSONP, sooo …

La première étape consiste à créer votre fonction qui gérera le JSON:

 function hooray(json) { // dealin wit teh jsonz } 

Assurez-vous que cette fonction est accessible au niveau global.

Ensuite, ajoutez un élément de script au DOM:

 var script = document.createElement('script'); script.src = 'http://domain.com/?function=hooray'; document.body.appendChild(script); 

Le script va charger le JavaScript que le fournisseur de l'API crée et l'exécuter.

J'ai une bibliothèque javascript pure pour faire cela https://github.com/robertodecurnex/J50Npi/blob/master/J50Npi.js

Regardez-le et faites-le moi savoir si vous avez besoin d'aide pour utiliser ou comprendre le code.

Btw, vous avez ici un exemple d'utilisation simple: http://robertodecurnex.github.com/J50Npi/

La façon dont j'utilise jsonp comme ci-dessous:

 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) }) } 

Puis utilisez la méthode 'jsonp' comme ceci:

 jsonp('http://xxx/cors').then(function(data){ console.log(data) }) 

référence:

JavaScript XMLHttpRequest utilisant JsonP

http://www.w3ctech.com/topic/721 (parler de la manière d'utiliser Promise)

 /** * 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); }); })(); 

Exemple d'utilisation:

 const data = await load('http://api.github.com/orgs/kriasoft'); 

J'ai écrit une bibliothèque pour gérer cela, aussi simplement que possible. Pas besoin de le rendre externe, c'est une seule fonction. Contrairement à d'autres options, ce script se nettoie après lui-même et est généralisé pour faire d'autres demandes au moment de l'exécution.

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); }; }); } 
 /** * 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' );