Skip to content

能否使用JSONP+代理方案解决跨域问题? #11

@PIKACHUIM

Description

@PIKACHUIM

一个 JSONP 的步骤实质

客户端发送 script 请求,参数中带着处理返回数据的回调函数的名字 (通常是 callback),如请求 script 的 url 是:
http://127.0.0.1:8000/?callback=getMsg
服务端收到请求,以回调函数名和返回数据组成立即执行函数的字符串,比如:其中 callback 的值是客户端发来的回调函数的名字,假设回调函数的名字是 getMsg,返回脚本的内容就是:
getMsg("{name: 'Yang Min', age: '8'}");
客户端收到 JavaScript 脚本内容后,立即执行脚本,这样就实现了获取跨域服务器数据的目的。
很明显,由于 JSONP 技术本质上利用了 script 脚本请求,所以只能实现 GET 跨域请求,这也是 JSONP 跨域的最大限制。
由于 server 产生的响应为 json 数据的包装(故称之为 jsonp,即 json padding),形如:getMsg("{name: 'Yang Min', age: '8'}")

JSONP 封装

客户端参考代码:

const jsonp = ({ url, params, callbackName }) => {
  const generateURL = () => {
    let dataStr = "";
    for (let key in params) {
      dataStr += `${key}=${params[key]}&`;
    }
    dataStr += `callback=${callbackName}`;
    return `${url}?${dataStr}`;
  };
  return new Promise((resolve, reject) => {
    // 初始化回调函数名称
    callbackName =
      callbackName ||
      "cb" +
        Math.random()
          .toString()
          .replace(".", "");
    let scriptEle = document.createElement("script");
    scriptEle.src = generateURL();
    document.body.appendChild(scriptEle);

    // 绑定到 window 上,为了后面调用
    window[callbackName] = data => {
      resolve(data);
      // script 执行完了,成为无用元素,需要清除
      document.body.removeChild(scriptEle);
    };
  });
};

jsonp({
  url: "http://127.0.0.1:8000/",
  params: {
    name: "Yang Min",
    age: "8"
  },
  callbackName: "getData"
})
  .then(data => JSON.parse(data))
  .then(data => {
    console.log(data); // {name: "Yang Min", age: "8"}
  });

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions