127 votes

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

Puis-je effectuer une requête JSONP inter-domaine en JavaScript sans utiliser jQuery ou une autre bibliothèque externe ? Je voudrais utiliser JavaScript lui-même, puis analyser les données et en faire un objet pour pouvoir les utiliser. Dois-je utiliser une bibliothèque externe ? Si non, comment puis-je le faire ?

0 votes

153voto

Matt Ball Points 165937
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

2 votes

Voici un JSBin qui peut être utilisé pour manipuler JSONP de Wikipedia. Il a été référencé dans cette réponse .

1 votes

Je pense qu'il est utile de préciser que la réponse doit être de la forme : foo(payload_of_json_data) l'idée étant que lorsqu'il est chargé dans la balise script, il appelle la fonction foo avec la charge utile déjà sous forme d'objet javascript et aucune analyse syntaxique n'est nécessaire.

0 votes

@WillMunn Je ne pense pas que cela soit possible avec JSONP. Il s'agit d'un hack datant de l'époque pré-CORS. Pour quoi avez-vous besoin de définir des en-têtes ? Le serveur doit spécifiquement accepter les requêtes JSONP, il doit donc être configuré pour servir de manière saine.

37voto

sobstel Points 159

Exemple léger (avec prise en charge de onSuccess et onTimeout). Vous devez passer le nom du callback 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
});

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

31voto

dewd Points 891

Qu'est-ce que JSONP ?

La chose importante à retenir avec jsonp est qu'il ne s'agit pas réellement d'un protocole ou d'un type de données. C'est juste un moyen de charger un script à la volée et traiter le script qui est introduit dans la page. Dans l'esprit de JSONP, cela signifie introduire un nouvel objet javascript du serveur dans l'application cliente/ script.

Quand JSONP est-il nécessaire ?

Il s'agit d'une méthode permettant à un domaine d'accéder aux données d'un autre dans la même page ou de les traiter de manière asynchrone. Principalement, il est utilisé pour remplacer les restrictions CORS (Cross Origin Resource Sharing) qui se produiraient avec une requête XHR (ajax). Les chargements de script ne sont pas soumis aux restrictions CORS.

Comment cela se passe-t-il ?

L'introduction d'un nouvel objet javascript à partir du serveur peut être mise en œuvre de plusieurs façons, mais la pratique la plus courante consiste à ce que le serveur exécute une fonction "callback", à laquelle est passé l'objet requis. La fonction de rappel est simplement une fonction que vous avez déjà mise en place sur le client, qui le script vous chargez les appels au point le script pour traiter les données qui lui sont transmises.

Exemple :

J'ai une application qui enregistre tous les objets se trouvant au domicile d'une personne. Mon application est configurée et je veux maintenant récupérer tous les objets qui se trouvent dans la chambre principale.

Ma demande est sur app.home.com . Les apis dont j'ai besoin pour charger les données se trouvent à l'adresse suivante api.home.com .

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

Idéalement, configurez les choses de manière à permettre le XHR du domaine x.

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 Access-Control-Allow-Origin: élément d'en-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" Cette méthode est beaucoup plus sûre que la mise en place de JSONP. La raison en est que app.home.com peut obtenir tout ce qu'il veut de api.home.com sans api.home.com donnant à CORS un accès à l'ensemble de l'internet.

La solution XHR ci-dessus n'est pas possible. Configurer JSONP sur mon client script : J'ai mis en place une fonction pour traiter la réponse du serveur lorsque je fais la demande d'accès au serveur. Appel JSONP. :

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

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

Ensuite, le client configure une balise script comme telle :

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

document.querySelector('head').appendChild(script);

Ceci charge le script et appelle immédiatement window.processJSONPResponse() comme écrit/écho/imprimé par le serveur. Les données transmises en tant que paramètre de la fonction sont maintenant stockées dans le fichier dataFromServer variable locale et vous pouvez en faire ce que vous voulez.

Nettoyer

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

script.parentNode.removeChild(script);

17voto

sdleihssirhc Points 18791

Si je comprends bien, vous utilisez en fait les balises script avec JSONP, donc...

La première étape consiste à créer la fonction qui traitera le JSON :

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

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

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

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

Le script chargera le JavaScript que le fournisseur d'API construit, et l'exécutera.

2 votes

Merci à tous. Je l'ai lancé sur Internet à la recherche de données, puis j'ai fait quelque chose avec. J'ai utilisé eval() sur les données de la réponse, ce qui m'a aidé à gérer l'objet - le tableau qu'il est (je pense). {Il a été difficile de comprendre l'analyse syntaxique avec mon intelligence limitée, mais j'ai finalement réussi à en extraire la valeur}. Fantastique.

0 votes

@Dave @Matt Peut-être que je Je suis floue sur JSONP, mais vous ne devriez pas avoir besoin de eval o parse ou quoi que ce soit. Vous devriez obtenir du JavaScript que le navigateur peut simplement exécuter, non ?

0 votes

C'est ma faute, désolé pour la confusion. Essayer d'extraire la chose (valeur ? propriété ?) du tableau me faisait tourner la tête (l'imbrication, le callback, le tableau, l'élément, l'objet, la chaîne de caractères, la valeur, les crochets, les parenthèses...). J'ai supprimé l'utilisation de eval et j'ai quand même obtenu la propriété (valeur ?) du tableau (objet?élément ?) que je voulais.

13voto

derek Points 131

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)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X