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

IT技术 javascript jsonp
2021-01-19 19:40:26

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

6个回答
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
我认为值得指出的是,响应的形式应该是: foo(payload_of_json_data),其想法是当它被加载到脚本标签中时,它会调用 foo 函数,有效载荷已经作为 javascript 对象并且不需要解析。
2021-03-11 19:40:26
你是对的,我误读了一些 api 文档,有一个特殊的查询参数可以在使用 jsonp appologies 时执行我想要的操作。
2021-03-14 19:40:26
@WillMunn 不用担心。很高兴你能解决它!
2021-03-20 19:40:26
@WillMunn 我认为 JSONP 不可行。这是 CORS 之前的黑客攻击。你需要为什么设置标题?服务器特别需要接受 JSONP 请求,因此应将其设置为以合理的方式提供服务。
2021-03-22 19:40:26
这是一个 JSBin,可用于处理来自维基百科的JSONP这个答案中引用了
2021-04-08 19:40:26

轻量级示例(支持 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

什么是 JSONP?

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

什么时候需要 JSONP?

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

怎么做的

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

例子:

我有一个应用程序可以记录某人家中的所有项目。我的应用程序已设置,现在我想检索主卧室中的所有物品。

我的应用程序在app.home.com. 我需要从中加载数据的 api 位于api.home.com.

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

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

理想情况下,由于 api 和应用程序在同一个域中,我可能有权在api.home.com. 如果我这样做,我可以添加一个Access-Control-Allow-Origin: 标题项,授予对app.home.com. 假设 header 设置如下:Access-Control-Allow-Origin: "http://app.home.com",这比设置 JSONP 安全得多。这是因为无需让 CORS 访问整个互联网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);
非常感谢,这对我的项目帮助很大。一个小问题:我收到了SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data. 向数据添加单引号后,一切正常,因此:"processJSONPResponse('{"room":"main bedroom","items":["bed","chest of drawers"]}');"
2021-04-01 19:40:26

我的理解是,您实际上将脚本标记与 JSONP 一起使用,所以...

第一步是创建将处理 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);

该脚本将加载 API 提供者构建的 JavaScript,并执行它。

感谢大家。得到它通过互联网拍摄以搜索一些数据,然后我用它做一些事情。我在响应数据上使用了 eval() ,它帮助我处理对象 - 它是(我认为)的数组。{这是一只用我有限的脑力解析出来的熊,但我终于从中提取了value}。极好的。
2021-03-11 19:40:26
@戴夫@马特也许我对JSONP模糊,但你不应该需要evalparse什么的。您应该获得浏览器可以执行的 JavaScript,对吗?
2021-03-31 19:40:26
我的错,很抱歉造成混乱。试图从数组中取出东西(值?属性?)让我头晕目眩(嵌套、回调、数组、元素、对象、字符串、值、大括号、方括号......)。我删除了对 eval 的使用,但仍然从我想要的数组(对象?元素?)中获得了属性(值?)。
2021-04-01 19:40:26

我使用 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);
});

参考:

使用 JsonP 的 JavaScript XMLHttpRequest

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

终止分配 script.src = src; 添加“;” 到所有作业结束
2021-03-24 19:40:26