sailei1 发表于 2013-1-29 08:35:19

Sencha Touch 2 Jsonp原理

JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
//Sencha Touch 2 Jsonp 核心源码Ext.define('Ext.data.JsonP', {    alternateClassName: 'Ext.util.JSONP',    /* Begin Definitions */    singleton: true,    /* End Definitions */    /**   * Number of requests done so far.   * @private   */    requestCount: 0,    /**   * Hash of pending requests.   * @private   */    requests: {},    /**   * @property {Number}    * A default timeout (in milliseconds) for any JsonP requests. If the request has not completed in this time the failure callback will   * be fired.   */    timeout: 30000,    /**   * @property {Boolean} disableCaching   * `true` to add a unique cache-buster param to requests.   */    disableCaching: true,    /**   * @property {String} disableCachingParam   * Change the parameter which is sent went disabling caching through a cache buster.   */    disableCachingParam: '_dc',    /**   * @property {String} callbackKey   * Specifies the GET parameter that will be sent to the server containing the function name to be executed when the   * request completes. Thus, a common request will be in the form of:      * `url?callback=Ext.data.JsonP.callback1`   */    callbackKey: 'callback',    /**   * Makes a JSONP request.   * @param {Object} options An object which may contain the following properties. Note that options will take   * priority over any defaults that are specified in the class.   *   * @param {String} options.urlThe URL to request.   * @param {Object} An object containing a series of key value pairs that will be sent along with the request.   * @param {Number} See {@link #timeout}   * @param {String} See {@link #callbackKey}   * @param {String} See {@link #callbackKey}   *   The function name to use for this request. By default this name will be auto-generated: Ext.data.JsonP.callback1,   *   Ext.data.JsonP.callback2, etc. Setting this option to "my_name" will force the function name to be   *   Ext.data.JsonP.my_name. Use this if you want deterministic behavior, but be careful - the callbackName should be   *   different in each JsonP request that you make.   * @param {Boolean}See {@link #disableCaching}   * @param {String}   See {@link #disableCachingParam}   * @param {Function} A function to execute if the request succeeds.   * @param {Function} A function to execute if the request fails.   * @param {Function} A function to execute when the request completes, whether it is a success or failure.   * @param {Object}   The scope in which to execute the callbacks: The "this" object for the   *   callback function. Defaults to the browser window.   *   * @return {Object}request An object containing the request details.   */    request: function(options){      options = Ext.apply({}, options);      //<debug>      if (!options.url) {            Ext.Logger.error('A url must be specified for a JSONP request.');      }      //</debug>      var me = this,            disableCaching = Ext.isDefined(options.disableCaching) ? options.disableCaching : me.disableCaching,            cacheParam = options.disableCachingParam || me.disableCachingParam,            id = ++me.requestCount,            callbackName = options.callbackName || 'callback' + id,            callbackKey = options.callbackKey || me.callbackKey,            timeout = Ext.isDefined(options.timeout) ? options.timeout : me.timeout,            params = Ext.apply({}, options.params),            url = options.url,            name = Ext.isSandboxed ? Ext.getUniqueGlobalNamespace() : 'Ext',            request,            script;      params = name + '.data.JsonP.' + callbackName;      if (disableCaching) {            params = new Date().getTime();      }      script = me.createScript(url, params, options); //建立script标签实现跨域      me.requests = request = {            url: url,            params: params,            script: script,            id: id,            scope: options.scope,            success: options.success,            failure: options.failure,            callback: options.callback,            callbackKey: callbackKey,            callbackName: callbackName      };      if (timeout > 0) {            request.timeout = setTimeout(Ext.bind(me.handleTimeout, me, ), timeout);      }      me.setupErrorHandling(request);      me = Ext.bind(me.handleResponse, me, , true);//      me.loadScript(request);      return request;    },    /**   * Abort a request. If the request parameter is not specified all open requests will be aborted.   * @param {Object/String} request The request to abort.   */    abort: function(request){      var requests = this.requests,            key;      if (request) {            if (!request.id) {                request = requests;            }            this.handleAbort(request);      } else {            for (key in requests) {                if (requests.hasOwnProperty(key)) {                  this.abort(requests);                }            }      }    },    /**   * Sets up error handling for the script.   * @private   * @param {Object} request The request.   */    setupErrorHandling: function(request){      request.script.onerror = Ext.bind(this.handleError, this, );    },    /**   * Handles any aborts when loading the script.   * @private   * @param {Object} request The request.   */    handleAbort: function(request){      request.errorType = 'abort';      this.handleResponse(null, request);    },    /**   * Handles any script errors when loading the script.   * @private   * @param {Object} request The request.   */    handleError: function(request){      request.errorType = 'error';      this.handleResponse(null, request);    },    /**   * Cleans up any script handling errors.   * @private   * @param {Object} request The request.   */    cleanupErrorHandling: function(request){      request.script.onerror = null;    },    /**   * Handle any script timeouts.   * @private   * @param {Object} request The request.   */    handleTimeout: function(request){      request.errorType = 'timeout';      this.handleResponse(null, request);    },    /**   * Handle a successful response   * @private   * @param {Object} result The result from the request   * @param {Object} request The request   */    handleResponse: function(result, request){      var success = true;      if (request.timeout) {            clearTimeout(request.timeout);      }      delete this;      delete this.requests;      this.cleanupErrorHandling(request);      Ext.fly(request.script).destroy();      //数据响应返回      if (request.errorType) {            success = false;            Ext.callback(request.failure, request.scope, );      } else {            Ext.callback(request.success, request.scope, );      }      Ext.callback(request.callback, request.scope, );    },    /**   * Create the script tag given the specified url, params and options. The options   * parameter is passed to allow an override to access it.   * @private   * @param {String} url The url of the request   * @param {Object} params Any extra params to be sent   * @param {Object} options The object passed to {@link #request}.   */    createScript: function(url, params, options) {      var script = document.createElement('script');      script.setAttribute("src", Ext.urlAppend(url, Ext.Object.toQueryString(params)));      script.setAttribute("async", true);      script.setAttribute("type", "text/javascript");      return script;    },    /**   * Loads the script for the given request by appending it to the HEAD element. This is   * its own method so that users can override it (as well as {@link #createScript}).   * @private   * @param request The request object.   */    loadScript: function (request) {      Ext.getHead().appendChild(request.script);//装载 来自服务器端的js   }});

所以 服务端要这样写
boolean jsonP = false;String cb = request.getParameter("callback"); //传过来的 callback 参数 假如 Ext.data.JsonP.callbackif (cb != null) {    jsonP = true;    response.setContentType("text/javascript");} else {    response.setContentType("application/x-json");}Writer out = response.getWriter();if (jsonP) {    out.write(cb + "(");//这拼一下js 数据}out.print(dataBlock.toJsonString());if (jsonP) {    out.write(");");}

然后可以在页面上 输出
Ext.data.JsonP.callback({你的json 数据});
然后 主页面 script标签 加入这个 服务端的js, 实现跨域获取服务端数据
页: [1]
查看完整版本: Sencha Touch 2 Jsonp原理