jsonp的原理与实现

前端之家收集整理的这篇文章主要介绍了jsonp的原理与实现前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

1. 概述

jsonp是一种跨域通信的手段,它的原理其实很简单:

  1. 首先是利用script标签的src属性来实现跨域。

  2. 通过将前端方法作为参数传递到服务器端,然后由服务器端注入参数之后再返回,实现服务器端向客户端通信。

  3. 由于使用script标签的src属性,因此只支持get方法

2. 实现流程

  1. 设定一个script标签

    1. <script src="http://jsonp.js?callback=xxx"></script>
  2. callback定义了一个函数名,而远程服务端通过调用指定的函数并传入参数来实现传递参数,将fn(response)传递回客户端

    1. $callback = !empty($_GET['callback']) ? $_GET['callback'] : 'callback';
    2. echo $callback.'(.json_encode($data).)';
  3. 客户端接收到返回的js脚本,开始解析和执行fn(response)

3. jsonp简单实现

一个简单的jsonp实现,其实就是拼接url,然后将动态添加一个script元素到头部。

  1. function jsonp(req){
  2. var script = document.createElement('script');
  3. var url = req.url + '?callback=' + req.callback.name;
  4. script.src = url;
  5. document.getElementsByTagName('head')[0].appendChild(script);
  6. }

前端js示例

  1. function hello(res){
  2. alert('hello ' + res.data);
  3. }
  4. jsonp({
  5. url : '',callback : hello
  6. });

服务器端代码

  1. var http = require('http');
  2. var urllib = require('url');
  3.  
  4. var port = 8080;
  5. var data = {'data':'world'};
  6.  
  7. http.createServer(function(req,res){
  8. var params = urllib.parse(req.url,true);
  9. if(params.query.callback){
  10. console.log(params.query.callback);
  11. //jsonp
  12. var str = params.query.callback + '(' + JSON.stringify(data) + ')';
  13. res.end(str);
  14. } else {
  15. res.end();
  16. }
  17. }).listen(port,function(){
  18. console.log('jsonp server is on');
  19. });

然而,这个实现虽然简单,但有一些不足的地方:

  1. 我们传递的回调必须是一个全局方法,我们都知道要尽量减少全局的方法

  2. 需要加入一些参数校验,确保接口可以正常执行。

4. 可靠的jsonp实现

  1. (function (global) {
  2. var id = 0,container = document.getElementsByTagName("head")[0];
  3.  
  4. function jsonp(options) {
  5. if(!options || !options.url) return;
  6.  
  7. var scriptNode = document.createElement("script"),data = options.data || {},url = options.url,callback = options.callback,fnName = "jsonp" + id++;
  8.  
  9. // 添加回调函数
  10. data["callback"] = fnName;
  11.  
  12. // 拼接url
  13. var params = [];
  14. for (var key in data) {
  15. params.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
  16. }
  17. url = url.indexOf("?") > 0 ? (url + "&") : (url + "?");
  18. url += params.join("&");
  19. scriptNode.src = url;
  20.  
  21. // 传递的是一个匿名的回调函数,要执行的话,暴露为一个全局方法
  22. global[fnName] = function (ret) {
  23. callback && callback(ret);
  24. container.removeChild(scriptNode);
  25. delete global[fnName];
  26. }
  27.  
  28. // 出错处理
  29. scriptNode.onerror = function () {
  30. callback && callback({error:"error"});
  31. container.removeChild(scriptNode);
  32. global[fnName] && delete global[fnName];
  33. }
  34.  
  35. scriptNode.type = "text/javascript";
  36. container.appendChild(scriptNode)
  37. }
  38.  
  39. global.jsonp = jsonp;
  40.  
  41. })(this);

使用示例

  1. jsonp({
  2. url : "www.example.com",data : {id : 1},callback : function (ret) {
  3. console.log(ret);
  4. }
  5. });

5. 来源

个人博客

猜你在找的Json相关文章