जावास्क्रिप्ट के बिना जावास्क्रिप्ट से JSONP अनुरोध कैसे करें?


122

क्या मैं jQuery या अन्य बाहरी पुस्तकालय का उपयोग किए बिना जावास्क्रिप्ट में क्रॉस-डोमेन JSONP अनुरोध कर सकता हूं? मैं स्वयं जावास्क्रिप्ट का उपयोग करना चाहूंगा और फिर डेटा को पार्स करूंगा और इसे एक वस्तु बनाऊंगा ताकि मैं इसका उपयोग कर सकूं। क्या मुझे बाहरी पुस्तकालय का उपयोग करना होगा? यदि नहीं, तो मैं यह कैसे कर सकता हूं?


जवाबों:


151
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
यहाँ एक JSBin है जो JSONP से विकिपीडिया से फिडेल किया जा सकता है । इस उत्तर में इसका संदर्भ दिया गया था ।
rkagerer

1
मुझे लगता है कि यह इंगित करने के लायक है कि प्रतिक्रिया फॉर्म की होनी चाहिए:, foo(payload_of_json_data)विचार यह है कि जब यह स्क्रिप्ट टैग में लोड हो जाता है, तो यह फव फंक्शन को पेलोड के साथ पहले से ही एक जावास्क्रिप्ट ऑब्जेक्ट के रूप में कहता है और कोई पार्स करना आवश्यक नहीं है।
ऑक्टोपस

@WillMunn मुझे नहीं लगता कि JSONP के साथ यह संभव है। यह पूर्व-कोर दिनों से हैक है। आपको हेडर सेट करने की क्या आवश्यकता है? सर्वर को विशेष रूप से JSONP अनुरोधों को स्वीकार करने की आवश्यकता होती है, इसलिए इसे एक तरीके से सेवा करने के लिए सेट किया जाना चाहिए।
मैट बॉल

आप सही हैं, मैं कुछ एपीआई प्रलेखन को गलत करता हूं, जो कि मैं चाहता हूं कि jsonp एप्लायंस का उपयोग करते समय एक विशेष क्वेरी पैरामीटर हो।
मुन्न

@WillMunn कोई चिंता नहीं। खुशी है कि आप इसे सुलझाने में सक्षम थे!
मैट बॉल

37

हल्के उदाहरण (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


29

JSONP क्या है?

Jsonp के साथ याद रखने वाली महत्वपूर्ण बात यह है कि यह वास्तव में एक प्रोटोकॉल या डेटा प्रकार नहीं है। यह मक्खी पर एक स्क्रिप्ट को लोड करने और उस स्क्रिप्ट को संसाधित करने का एक तरीका है जो पृष्ठ पर पेश किया जाता है। JSONP की भावना में, इसका अर्थ है सर्वर से क्लाइंट एप्लिकेशन / स्क्रिप्ट में एक नई जावास्क्रिप्ट ऑब्जेक्ट को पेश करना।

JSONP की आवश्यकता कब है?

यह एक तरीके से एक ही पृष्ठ पर एक डोमेन से डेटा को एक्सेस / प्रोसेस करने की अनुमति देने की 1 विधि है। मुख्य रूप से, इसका उपयोग CORS (क्रॉस ओरिजिन रिसोर्स शेयरिंग) प्रतिबंधों को ओवरराइड करने के लिए किया जाता है, जो XHR (ajax) अनुरोध के साथ होता है। स्क्रिप्ट लोड कॉर्स प्रतिबंध के अधीन नहीं हैं।

यह कैसे किया जाता है

सर्वर से एक नई जावास्क्रिप्ट ऑब्जेक्ट को प्रस्तुत करना कई तरीकों से लागू किया जा सकता है, लेकिन सर्वर के लिए सबसे आम अभ्यास एक कॉलबैक फ़ंक्शन के निष्पादन को लागू करने के लिए है, जिसमें आवश्यक वस्तु उसमें पारित हो जाती है। कॉलबैक फ़ंक्शन केवल एक फ़ंक्शन है जिसे आपने पहले ही क्लाइंट पर सेट कर दिया है, जिसे आप जिस स्क्रिप्ट पर लोड करते हैं, वह उस डेटा को संसाधित करने के लिए स्क्रिप्ट लोड बिंदु पर लोड करता है।

उदाहरण:

मेरे पास एक एप्लिकेशन है जो किसी के घर में सभी वस्तुओं को लॉग करता है। मेरा एप्लिकेशन सेट हो गया है और मैं अब मुख्य बेडरूम में सभी वस्तुओं को पुनः प्राप्त करना चाहता हूं।

मेरा आवेदन चालू है app.home.com। जिन एपिसिस से मुझे डेटा लोड करने की आवश्यकता है, वे चालू हैं api.home.com

जब तक कि सर्वर को स्पष्ट रूप से इसे अनुमति देने के लिए सेट नहीं किया गया है, मैं इस डेटा को लोड करने के लिए ajax का उपयोग नहीं कर सकता, क्योंकि अलग-अलग उप-डोमेन पर भी पृष्ठ XHR कॉर्स प्रतिबंध के अधीन हैं।

आदर्श रूप से, एक्स-डोमेन एक्सएचआर की अनुमति देने के लिए चीजों को सेट करें

आदर्श रूप से, चूंकि एपीआई और ऐप एक ही डोमेन पर हैं, इसलिए मेरे पास हेडर सेट करने के लिए एक्सेस हो सकता है api.home.com। यदि मैं करता हूं, तो मैं एक Access-Control-Allow-Origin: हेडर आइटम को एक्सेस करने के लिए अनुदान दे सकता हूं app.home.com। हेडर मानकर सेट किया गया है: Access-Control-Allow-Origin: "http://app.home.com"यह JSONP सेट करने की तुलना में कहीं अधिक सुरक्षित है। ऐसा इसलिए है क्योंकि पूरे इंटरनेट पर कॉर्स को एक्सेस दिए बिना app.home.comवह सब कुछ प्राप्त कर सकता है जो वह चाहता है ।api.home.comapi.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);

2
बहुत बहुत धन्यवाद, इससे मुझे अपने प्रोजेक्ट में बहुत मदद मिली। एक छोटी सी समस्या: मुझे मिली है SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data। डेटा में एकल उद्धरण जोड़ने के बाद, सब कुछ ठीक काम करता है, इसलिए:"processJSONPResponse('{"room":"main bedroom","items":["bed","chest of drawers"]}');"
हेन वैन डाइक

17

मेरी समझ यह है कि आप वास्तव में JSONP, sooo के साथ स्क्रिप्ट टैग का उपयोग करते हैं ...

पहला चरण आपके फ़ंक्शन को बनाना है जो 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);

स्क्रिप्ट जावास्क्रिप्ट लोड करेगा जो एपीआई प्रदाता बनाता है, और इसे निष्पादित करता है।


2
सबको धन्यवाद। समझ गया कि कुछ डेटा की तलाश में इंटरनेट पर शूटिंग हो रही है और फिर मैं इसके साथ कुछ करता हूं। मैंने प्रतिक्रिया डेटा पर eval () का उपयोग किया जिससे मुझे ऑब्जेक्ट - सरणी से निपटने में मदद मिली जो यह है (मुझे लगता है)। {यह मेरी सीमित दिमागी ताकत के साथ पार्स करने वाला एक भालू था, लेकिन आखिरकार मुझे इसका मूल्य मिल गया}। बहुत खुबस।
डेव

@Dave @Matt शायद मैं कर रहा हूँ JSONP पर फजी, लेकिन आप की जरूरत नहीं होनी चाहिए evalया parseकुछ भी या। आपको जावास्क्रिप्ट प्राप्त करना चाहिए कि ब्राउज़र बस निष्पादित कर सकता है, है ना?
सलीडीहसीरहैक

मेरा बुरा, भ्रम के लिए खेद है। सरणी से चीज़ (मान? गुण?) प्राप्त करने की कोशिश कर रहा था मेरे सिर को स्पिन कर रहा था (घोंसला बनाना, कॉलबैक, सरणी, तत्व, वस्तु, स्ट्रिंग, मूल्य, घुंघराले कोष्ठक, कोष्ठक ...)। मैंने अपने उपयोग का निष्कासन हटा दिया और फिर भी मुझे सरणी (वस्तु? तत्व?) से संपत्ति (मूल्य?) मिली।
दवे

10

जिस तरह से मैं नीचे 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);
});

संदर्भ:

जावास्क्रिप्ट XMLHttpRequest JsonP का उपयोग कर

http://www.w3ctech.com/topic/721 (उपयोग के तरीके के बारे में बात करें)


1
असाइनमेंट्स script.src = src को समाप्त करें; जोड़ें ';' सभी असाइनमेंट के अंत तक
chdev77

6

मेरे पास एक शुद्ध जावास्क्रिप्ट लाइब्रेरी है जो https://github.com/robertodecurnex/J50Npi/blob/master/J50Npi.js

इस पर एक नज़र डालें और मुझे बताएं कि क्या आपको कोड का उपयोग करने या समझने में कोई मदद चाहिए।

Btw, आपके पास यहाँ सरल उपयोग उदाहरण हैं: http://robertodecurnex.github.com/J50Npi/


6
आपका समाधान मेरे उपयोग-मामले के लिए थोड़ा सरल था, इसलिए मैंने कई अनुरोधों को जोड़ा समर्थन gist.github.com/1431613
चाड Scira

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

1
window[callback] = nullफ़ंक्शन को एकत्रित करने की अनुमति देने के लिए मत भूलना ।
सुकीमा

3

मैंने इसे संभालने के लिए एक लाइब्रेरी लिखी, जितनी जल्दी हो सके। इसे बाहरी बनाने की जरूरत नहीं है, इसका सिर्फ एक कार्य है। कुछ अन्य विकल्पों के विपरीत, यह स्क्रिप्ट स्वयं के बाद साफ हो जाती है, और रनटाइम में आगे अनुरोध करने के लिए सामान्यीकृत होती है।

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

2

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


0
/**
 * 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इस पर कचरा संग्रहण कब किया जा सकता है?
सुकिमा

0

यदि आप एनपीएम के साथ ईएस 6 का उपयोग कर रहे हैं, तो आप नोड मॉड्यूल "भ्रूण-जोंसप" की कोशिश कर सकते हैं। Fetch API नियमित XHR कॉल के रूप में JsonP कॉल करने के लिए सहायता प्रदान करता है।

शर्त: आपको isomorphic-fetchअपने स्टैक में नोड मॉड्यूल का उपयोग करना चाहिए ।


0

बस sobstel का अच्छा जवाब के एक ES6 संस्करण चिपकाने:

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)
    })
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.