JQuery source code analysis series (35): Implementation and principles of Ajax-jsonp

Source: Internet
Author: User
Tags php server

The core of ajax is to obtain content not on this page through XmlHttpRequest, while the core of jsonp is to dynamically Add the <script> tag to call the js script json provided by the server. The core is: you can pass a callback parameter to the server. When the server returns data, the callback parameter is used as the function name to enclose JSON data, in this way, the client can customize its own functions to automatically process the returned data. The implementation methods of the jquery ext dojo class library are similar in that under the same-origin policy, the pages under a server cannot obtain data other than the server, however, img, iframe, script, and other tags are exceptions. These tags can request data on other servers through the src attribute. Using the open policy of the script tag, we can implement cross-origin request data. Of course, we also need the cooperation of the server. Let's take a look at a piece of jQuery processing jsonp by sending a php request to the client to copy the code $. ajax ({async: false, // load data synchronously, that is, wait until the ajax execution is complete and then execute the following statement url: 'http: // 192.168.1.114/yii/demos/test. php ', // different domain types: 'get', // jsonp mode. Only data in GET mode is valid: {'action': 'Aaron '}, // The array ype of the pre-passed parameter: 'jsonp', // data type jsonp: 'backfunc', // specify the callback function name, which is consistent with the received by the server, and return success: function (json) {console. log (json) ;}}) Copy code php server copy Code <? Php $ act = trim ($ _ GET ['action']); if ($ act = 'Aaron ') {echo trim ($ _ GET ['backfunc']). '('. json_encode (array ('status' => 1, 'info' => 'OK ')). ')' ;}?> Generally, the JavaScript code cannot be used for cross-origin requests. Therefore, you must use a special method to implement cross-origin, the principle is to use the <script> element's open policy. Here there are two important parameters: jsonpCallback: specify a callback function name for the jsonp request. This value is used to replace the random function name automatically generated by jQuery. This is mainly used for jQuery to generate a unique function name, which makes it easier to manage requests and conveniently provide callback functions and error handling. You can also specify the callback function name when you want the browser to cache the GET request. From jQuery 1.5, you can also use a function to set this parameter. In this case, the return value of this function is the result of jsonpCallback. Jsonp: Specifies the name of the callback function in a jsonp request. This value is used to replace "callback =? "The" callback "section of the URL parameter in this GET or POST request, for example, {jsonp: 'onjsonpload'} causes" onJsonPLoad =? "To the server. In jQuery 1.5, set jsonp to false to prevent jQuery from joining "? Callback "string URL or try to use" =? "Conversion. In this case, you should also set jsonpCallback explicitly. For example, {jsonp: false, jsonpCallback: "callbackName"}. When we normally request a JSON data, the server returns a JSON data string, when we use the JSONP mode to request data, the server returns a piece of executable JavaScript code, so we can see the last line of the server code $ _ GET ['backfunc']). '('. json_encode (array ('status' => 1, 'info' => 'OK ')). ') is to execute the backfunc method, and then pass the data through the callback method in the past OK, that is, the entire process is: the client sends a request, define an executable function name (jQuery is encapsulated here to automatically generate a callback function and fetch the data for the success attribute method to call, is not a callback handle passed), the server accepts this backfunc function name, and then sends the data out of jQue in the form of real parameters. Ry implementation: the implementation of different domains through ajax requests, the underlying layer is not dependent on XmlHttpRequest but script, so don't be confused by this method. In ajax requests, if the type is get post, in fact, only get is used internally, because its cross-domain principle is to dynamically load the src of the script, so we can only pass parameters through url, such as copying code $. ajax ({url: 'http: // 192.168.1.114/yii/demos/test. php ', // different domain types: 'get', // jsonp mode. Only data in GET mode is valid: {'action': 'Aaron '}, // The array ype of the pre-passed parameter: 'jsonp', // data type jsonp: 'backfunc', // specify the callback function name, which is consistent with the received by the server, and return back}) the copy code is actually converted into http: // 192.16 in jquery. 8.1.114/yii/demos/test. php? Backfunc = jquery2030020.393941527615_1402643146875 & action = aaron and then dynamically load <script type = "text/javascript" src = "http: // 192.168.1.114/yii/demos/test. php? Backfunc = jquery2030020.393941527615_1402643146875 & action = aaron "> </script> then the php side executes backfunc (passing parameters). Therefore, the process is divided into two steps: 1: preprocessing for jsonp, it is mainly to convert and splice these parameters, and then process the cache. Because jsonp also relies on loading scripts, it is necessary to disable the browser cache inspectPrefiltersOrTransports. After jsonp is pre-processed, also execute the recursion of inspect (dataTypeOrTransport); to disable this cache mechanism, copy the code var dataTypeOrTransport = prefilterOrFactory (options, originalOptions, jqXHR ); /*** handle for jonsp */if (typeof dataTypeOrTran Sport === "string "&&! SeekingTransport &&! Inspected [dataTypeOrTransport]) {// Add the cache settings flag // No cache is required // dataTypes: Array [2] // 0: "script" // 1: "json" options. dataTypes. unshift (dataTypeOrTransport); inspect (dataTypeOrTransport); return false;} else if (seekingTransport) {return! (Selected = dataTypeOrTransport);} copy the pre-processed code of the Code to copy the code // Detect, normalize options and install callbacks for jsonp requests // Add a specific type of filter to the pre-filter object // The added filter will format the parameter and add callbacksjQuery for THE jsonp request. ajaxPrefilter ("json jsonp", function (s, originalSettings, jqXHR) {var callbackName, overwritten, responseContainer, // if it is form submission, you need to check the data jsonProp = s. jsonp! = False & (jsonsonp. test (s. url )? "Url": typeof s. data = "string "&&! (S. contentType | ""). indexOf ("application/x-www-form-urlencoded") & amp; jsonsonp. test (s. data) & "data"); // Handle iff the expected data type is "jsonp" or we have a parameter to set // This method only processes jsonp, if the json url or data has jsonp features, it will be treated as jsonp for processing if (jsonProp | s. dataTypes [0] === "jsonp") {// Get callback name, remembering preexisting value associated with it/s. when jsonpCallback is used, the execution function uses the return value as the callback function name callbackNam. E = s. jsonpCallback = jQuery. isFunction (s. jsonpCallback )? S. jsonpCallback (): s. jsonpCallback; // Insert callback into url or form data // Insert callback url or form data // "test. php? Symbol = IBM & callback = jQuery20309245402452070266_1402451299022 "if (jsonProp) {s [jsonProp] = s [jsonProp]. replace (jsonsonp, "$1" + callbackName);} else if (s. jsonp! = False) {s. url + = (ajax_rquery.test (s. url )? "&":"? ") + S. jsonp + "=" + callbackName;} // Use data converter to retrieve json after script execution s. converters ["script json"] = function () {if (! ResponseContainer) {jQuery. error (callbackName + "was not called");} return responseContainer [0];}; // force json dataType // force-to-convert type s. dataTypes [0] = "json"; // Install callback // Add a global temporary function overwritten = window [callbackName]; window [callbackName] = function () {responseContainer = arguments;}; // Clean-up function (fires after converters) // after the code is executed, clear all the functions jqXHR. always (function () {// Rest Ore preexisting value window [callbackName] = overwritten; // Save back as free if (s [callbackName]) {// make sure that re-using the options doesn't screw things around s. jsonpCallback = originalSettings. jsonpCallback; // save the callback name for future use oldCallbacks. push (callbackName);} // Call if it was a function and we have a response if (responseContainer & jQuery. isFunction (overwritte N) {overwritten (responseContainer [0]);} responseContainer = overwritten = undefined;}); // Delegate to script return "script ";}}); copying the code jquery loads a global function in the window object. When the code is inserted, the function is executed and removed after execution. At the same time, jquery also optimizes non-Cross-origin requests. If the request is under the same domain name, it will work like a normal Ajax request. The distributor executes the code: When all our parameters are converted, the request sender processes the specific reason for sending, because the request target ajax is involved in jsonp processing, the actual request is not handled through xhr. send (XmlHttpRequest) is sent but loaded using the get script. Therefore, when the transports object initializes the component, two processors are generated *: Array [1] For xhr script: array [1] for the script, the jsonp mode is transport = inspectPrefiltersOrTransports (transports, s, options, jqXHR); then the obtained transport will be based on the current processing type, to select which transmitter (*, script) is used for the script requestor to copy the code jQuery. ajaxTransport ("script", func Tion (s) {// This transport only deals with cross domain requests if (s. crossDomain) {var script, callback; return {send: function (_, complete) {script = jQuery ("<script> "). prop ({async: true, charset: s. scriptCharset, // "http: // 192.168.1.114/yii/demos/test. php? Backfunc = jquery20308569577629677951_1401_2881663 & action = aaron & _ = 1402642881664 "src: s. url }). on ("load error", callback = function (evt) {script. remove (); callback = null; if (evt) {complete (evt. type = "error "? 404: 200, evt. type) ;}}); document. head. appendChild (script [0]) ;}, abort: function () {if (callback) {callback () ;}}}}); copy the code and you will understand it now.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.