Hur gör man en JSONP-förfrågan från Javascript utan JQuery?


Kan jag göra en cross-domain JSONP-begäran i JavaScript utan att använda jQuery eller något annat externt bibliotek? Jag skulle vilja använda JavaScript själv och sedan parsar datan och göra den till ett objekt så att jag kan använda den. Måste jag använda ett externt bibliotek? Om inte, hur kan jag göra det?

Svar #1

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

Svar #2

Lättvikts exempel (med stöd för onSuccess och onTimeout). Du behöver skicka callback-namn inom URL:en om du behöver det.

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

Exempel på användning:

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

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

Svar #3

Vad är JSONP?

Det viktiga att komma ihåg med jsonp är att det faktiskt inte är ett protokoll eller datatyp. Det är bara ett sätt att ladda ett skript på språng och bearbeta skriptet som introduceras på sidan. I JSONP:s anda innebär detta att införa ett nytt JavaScript-objekt från servern till klientapplikationen/skriptet.

När behövs JSONP?

Det är en metod för att tillåta ett domän att få åtkomst till/behandla data från ett annat på samma sida asynkront. Huvudsakligen används det för att åsidosätta CORS (Cross Origin Resource Sharing)-begränsningar som skulle uppstå vid en XHR (ajax)-förfrågan. Scriptladdningar omfattas inte av CORS-begränsningar.

Hur görs det

Att introducera ett nytt JavaScript-objekt från servern kan implementeras på många sätt, men den vanligaste metoden är att servern implementerar utförandet av en 'callback'-funktion, med det erforderliga objektet som skickas in i den. Callback-funktionen är bara en funktion som du redan har ställt in på klienten, som scriptet du laddar anropar vid den punkt då scriptet laddas för att bearbeta de data som skickas in i den.

Exempel:

Jag har en applikation som loggar alla föremål i någons hem. Min applikation är uppsatt och jag vill nu hämta alla föremål i huvudsovrummet.

Min applikation finns på app.home.com. API:erna jag behöver för att ladda data från finns på api.home.com.

Om inte servern uttryckligen är inställd för att tillåta det, kan jag inte använda ajax för att ladda dessa data, eftersom även sidor på separata underdomäner är föremål för XHR CORS-begränsningar.

Idealiskt sett, ställ in saker så att x-domän XHR tillåts

Idealiskt, eftersom API:et och appen är på samma domän, kanske jag har tillgång att ställa in headers på api.home.com. Om jag gör det kan jag lägga till ett Access-Control-Allow-Origin: -headerobjekt som ger åtkomst till app.home.com. Förutsatt att headern är inställd som följer: Access-Control-Allow-Origin: "http://app.home.com", är detta mycket säkrare än att ställa in JSONP. Detta beror på att app.home.com kan få allt den vill ha från api.home.com utan att api.home.com ger CORS-åtkomst till hela internet.

Lösningen ovan med XHR är inte möjlig. Ställ in JSONP på mitt klientskript: Jag skapade en funktion för att bearbeta svaret från servern när jag gör JSONP-anropet.:

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

Servern kommer att behöva ställas in för att returnera ett litet skript som ser ut ungefär som "processJSONPResponse('{"room":"main bedroom","items":["bed","chest of drawers"]}');" Det kan vara utformat för att returnera en sådan sträng om något som //api.home.com?getdata=room&room=main_bedroom anropas.

Sedan sätter klienten upp en script-tagg på följande sätt:

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

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

Detta laddar skriptet och anropar genast window.processJSONPResponse() som skrivits/ ekats/ skrivit ut av servern. Data som skickas in som parameter till funktionen lagras nu i den lokala variabeln dataFromServer och du kan göra med den vad du behöver.

Städa upp

När klienten har datan, dvs. omedelbart efter att skriptet har lagts till i DOM, kan skriptelementet tas bort från DOM:

script.parentNode.removeChild(script);

Svar #4

Min förståelse är att du faktiskt använder script-taggar med JSONP, sååå...

Det första steget är att skapa din funktion som kommer att hantera JSON:

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

Se till att denna funktion är tillgänglig på en global nivå.

Nästa, lägg till ett script-element i DOM:

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

Skriptet kommer att ladda JavaScript som API-leverantören bygger och köra det.

Svar #5

sättet jag använder jsonp på som nedan:

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

använd sedan metoden 'jsonp' så här:

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

referens:

JavaScript XMLHttpRequest med JsonP

http://www.w3ctech.com/topic/721 (prata om sättet att använda Promise)

Relaterade artiklar