如何在没有JQuery的情况下从Javascript发出JSONP请求?

Dav*_*ave 117 javascript jsonp

我可以在不使用jQuery或其他外部库的情况下在JavaScript中创建跨域JSONP请求吗?我想使用JavaScript本身,然后解析数据并使其成为一个对象,以便我可以使用它.我必须使用外部库吗?如果没有,我该怎么办?

Mat*_*all 148

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
Run Code Online (Sandbox Code Playgroud)

  • 这是一个可以用来从维基百科中[摆弄JSONP](http://jsbin.com/omujex/10/edit)的JSBin.它在[此答案]中引用(http://stackoverflow.com/questions/15293680/fetch-random-excerpt-from-wikipedia-javascript-client-only/15293681#15293681). (2认同)

sob*_*tel 36

轻量级示例(支持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;
})();
Run Code Online (Sandbox Code Playgroud)

样品用法:

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

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


dew*_*ewd 26

什么是JSONP?

使用jsonp要记住的重要一点是它实际上不是协议或数据类型.它只是一种即时加载脚本并处理引入页面的脚本的方法.本着JSONP的精神,这意味着将新的javascript对象从服务器引入客户端应用程序/脚本.

什么时候需要JSONP?

它是一种允许一个域同时访问/处理同一页面中另一个域的数据的方法.主要是,它用于覆盖在XHR(ajax)请求中发生的CORS(跨源资源共享)限制.脚本加载不受CORS限制.

怎么做

从服务器引入新的javascript对象可以通过多种方式实现,但最常见的做法是服务器实现"回调"函数的执行,并将所需的对象传递给它.回调函数只是您已在客户端上设置的函数,您加载的脚本在脚本加载时调用函数来处理传入其中的数据.

例:

我有一个应用程序将所有项目记录在某人的家中.我的应用程序已设置好,我现在想要检索主卧室中的所有项目.

我的申请是app.home.com.我需要加载数据的apis是打开的api.home.com.

除非明确设置服务器以允许它,否则我不能使用ajax来加载此数据,因为即使是单独子域上的页面也受XHR CORS限制.

理想情况下,设置允许x-domain XHR

理想情况下,由于api和app位于同一个域中,因此我可以访问以设置标头api.home.com.如果我这样做,我可以添加一个Access-Control-Allow-Origin:授予访问权限的标题项app.home.com.假设标头设置如下:Access-Control-Allow-Origin: "http://app.home.com",这比设置JSONP安全得多.这是因为app.home.com可以获得它想要的一切api.home.com而无需api.home.comCORS访问整个互联网.

上述XHR解决方案是不可能的.设置JSONP在我的客户端脚本上: 我设置了一个函数来在我进行JSONP调用时处理来自服务器的响应.:

function processJSONPResponse(data) {
    var dataFromServer = data;
}
Run Code Online (Sandbox Code Playgroud)

服务器需要设置为返回一个迷你脚本,看起来像是"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);
Run Code Online (Sandbox Code Playgroud)

这会加载脚本并立即调用window.processJSONPResponse()服务器写入/ echo /打印出来.作为函数的参数传入的数据现在存储在dataFromServer局部变量中,您可以随意使用它.

清理

一旦客户端拥有数据,即.将脚本添加到DOM后,可以立即从DOM中删除脚本元素:

script.parentNode.removeChild(script);
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢,这对我的项目帮助很大。一个小问题:我收到了`SyntaxError:JSON.parse:JSON 数据的第 1 行第 2 列的意外字符`。向数据添加单引号后,一切正常,所以:`"processJSONPResponse('{"room":"main卧室","items":["bed","chest of drawers"]}');"` (2认同)

sdl*_*rhc 17

我的理解是你实际上使用了带有JSONP的脚本标签,sooo ......

第一步是创建将处理JSON的函数:

function hooray(json) {
    // dealin wit teh jsonz
}
Run Code Online (Sandbox Code Playgroud)

确保可以在全局级别访问此功能.

接下来,向DOM添加一个脚本元素:

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

该脚本将加载API提供程序构建的JavaScript并执行它.

  • 感谢大家.通过互联网搜索一些数据然后我用它做了一些事情.我在响应数据上使用了eval(),这有助于我处理对象 - 数组(我认为).{这是一只熊,用我有限的脑力来解析出来,但我终于从中获得了价值}.太棒了. (2认同)

小智 8

我使用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)
    });
}
Run Code Online (Sandbox Code Playgroud)

然后像这样使用'jsonp'方法:

jsonp('http://xxx/cors').then(function(data){
    console.log(data);
});
Run Code Online (Sandbox Code Playgroud)

参考:

使用JsonP的JavaScript XMLHttpRequest

http://www.w3ctech.com/topic/721(谈谈使用方式Promise)


rob*_*nex 6

我有一个纯粹的JavaScript库来做到这一点https://github.com/robertodecurnex/J50Npi/blob/master/J50Npi.js

看看它,如果您需要使用或理解代码,请告诉我.

顺便说一下,这里有一个简单的用法示例:http://robertodecurnex.github.com/J50Npi/

  • 您的解决方案对我的用例来说有点过于简单,所以我添加了多个请求支持https://gist.github.com/1431613 (6认同)

Kon*_*kus 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);
  });
})();
Run Code Online (Sandbox Code Playgroud)

使用范例:

const data = await load('http://api.github.com/orgs/kriasoft');
Run Code Online (Sandbox Code Playgroud)