How to Implement kissy of JSONP in js framework

Source: Internet
Author: User
Tags call back getscript

How to Implement kissy of JSONP in js framework
Introduction to JSONP principles (this reminds programmers of cross-origin requests using a <script> that is not affected by the same-origin policy. JSON data alone is only data. It does not make sense to be added to the page by <script>. Therefore, a variable must be used as the function name, that is, the "P ", JSON data is passed as function parameters. Then, the function is executed after the browser is loaded. Therefore, this function must be a dynamically created global variable. JSONP is actually a dynamic loading of js scripts. To pass a variable to the backend, we need a parameter. Common parameters include jsonp, jsonpCallback, and callback. Of course, this requires backend cooperation. In addition, XHR2 CORS supports cross-origin. You can see that the implementation process of the js library Ajax module is divided into three parts: XHR object, upload transport, and converter converters. The first is to create an XHR object. It may also be a pseudo XHR created by a programmer to implement most of the XHR2 interfaces in various browsers, at the beginning, you must first create an XHR object. Then, send a request to the server in form or script form. Here there is a concept of transfer. It is responsible for sending the request, and uses different transfer methods as needed. Then we need to convert the returned data to the form required by the programmer, which requires a converter. Knowledge about the kissy framework (I think about util. js: a module of kissy, which may be called utils, is more suitable. It mainly provides auxiliary functions commonly used by the kissy framework. Helper functions are very important to a framework, such as common helper functions such as each, filter, and isArray. There is also the util related to this blog. parseJson. I think it is very important. I don't know why this is not found in the official API provided by kissy 5.0, but I found it in the source code of github, util/lib/util/json. js can be seen here. Util. in addition to being practical, mix is also interesting. It can be used to add a whitelist. The attributes of the Copied object will be copied only in the whitelist, underscore also has a similar parameter used for blacklist. (I think that the efficiency of the two methods will be different because of different use cases, so util should not be improved, simply to be different from underscore (if I am wrong, please leave a message to learn more... event-custom.js: Custom events in the hands of jQuery industry giants (jQuery. on), kissy will naturally have it. Is the kissy module event-custom. It uses the PubSub mode (actually the observer mode). A Custom Event Type publish (Pub) subscribes to multiple callback functions that are responsible for event processing (Sub ), callback is performed when an event is triggered. PubSub mode is used to process such asynchronous events, but it has nothing to do with Asynchronization. It is synchronous and custom events do not enter js Event Loop. Node is very fond of this mode. The EventEmitter object of events uses the PubSub mode. I used it for a simple test. Copy the code var events = require ("events"); var emitter = new events. eventEmitter (); var async = false; emitter. on ('eventtype', function () {console. assert (async) ;}); emitter. emit ('eventtype'); // error false = trueasync = true; copy the code and use the asynchronous var async = false implemented by setTimeout; setTimeout (function () {console. assert (async); // No error reported}, 0); async = true; promise: The promise module of kissy uses the Promise/A + specification, it is an iterative version of Promise/. Promise can make Ajax-rich pages ask for callback pyramid nightmares, and also make it easy for js programmers to use Asynchronization ~ The details are not described here. First of all, we need to clarify the several steps of jsonp implementation. We also mentioned in the introduction that first generate a URL, then generate a scirpt tag to send the request, then convert the data, and finally call back. Next, let's take a step-by-step look at the Code implemented by kissy jsonp to go directly to IO. jsonp (url, data, callback) We found the kissy IO module on github, the first is io. js, you can see the copy code var serializer = require ('. /io/form-serializer '); var IO = require ('. /io/base'); var util = require ('util'); require ('. /io/xhr-transport '); require ('. /io/script-transport '); require ('. /io/jsonp '); require ('. /io/form '); require ('. /io/iframe-transport '); require ('. /io/methods '); copy the code to see xhr- Transport, script-transport, iframe-transport this is loading various uploaders, we need to note that script-transport, jsonp will use it. Base. js is the basis of the IO module. We will go back later. This API naturally calls I/O, just as jQuery. get is short for jQuery. ajax. Run the jsonp: function (url, data, callback) {if (typeof data = 'function') {callback = data; data = undefined ;} return get (url, data, callback, 'jsonp')} copy the code getScript: require. load copy code function get (url, data, callback, dataType, type) {// The data parameter can be omitted if (typeof data = 'function') {dataType = callback; callback = data; data = undefined;} return IO ({type: type | 'get', url: url, data: Data, complete: callback, dataType: dataType});} copy the call IO in the Code, set dataType to jsonp, AND get request. Other parameters are the same as common ajax parameters. dataType is obviously a clue. Specifically in getScript: require. load, because getScript is responsible for sending scripts, and jsonp is also a getScript. Var IO = require ('. /base'); then go to base. in js, let's take a look at the summary: IO. js loads various js files, adds several convenient portals to IO, and calls io functions in a unified manner. Base. first of all, js will be attracted by defaconfig config, because various default configurations required by Ajax are set here, such as HTTP request mothods, MIME type, and encoding, the general converter settings are also in this object. The next step is to set the configuration function setUpConfig (c). We still don't read it before we know what parameters will be passed in (in fact, we can also look at the code to guess a hundred times better ). Find the IO function directly. The parameter is c. Self is an instance of IO functions. Then, set the promise mode to IO. You can use the chain operation ~ (I also read yiminghe chicory comments! '2017-2-07 yiminghe@gmail.com-return Promise type object, you can chain it! 'Slot... haomeng !). Self. userConfig = c; c = setUpConfig (c); our parameters are now passed to setConfig and a new parameter object is generated. To avoid interrupting the analysis of IO functions. Let's analyze it later. Util. mix is to clone the following objects to self, and then add a bunch of attributes such as config, transport, and timeoutTimer. Then, declare the upload constructor and the upload variable, and then trigger the start event! This marks the beginning of IO! Next, select the corresponding upload task based on dataType and create an instance. Then there are Ajax-related headers, readyState, status, and other settings, which has nothing to do with jsonp. Then it uses setTimeout to simulate the Timeout function. There's nothing to do in the future. At the end of base. js, we added methods like setupConfig, setupTransport, and getTransport to the IO function to implement config settings and other functions. What we care about is setupTransport and the upload settings. Now let's look back at setupConfig. The returned value is a new config object. At the beginning, clone the parameter c to defaultConfig in depth, and then generate the required config value to c, like var context = c. context; delete c. context; c = util. mix (util. clone (defaconfig config), c, {deep: true}); c. context = context | c; context indicates the "Environment" of the callback function after the request (context dummies translation) -- success, error, and complete. The variable that is declared later is skipped. uri = c. uri is a url object containing all url-related parameters. Uri. query consists of querystring name/value pairs in the url to form a JSON format object/array. We excluded the cross-origin-independent processing process. Most of jsonp is unavailable ~ DataType = c. dataType = util. trim (dataType | '*'). split (rspace); if (! ('Cache' in c) & util. inArray (dataType [0], ['script', 'jsonp']) {c. cache = false;} util. trim removes spaces before and after dataType, rspace =/\ s +/, and split splits dataType into sub-string arrays by spaces. Then confirm that the ype is jsonp. C. indicates whether a script or jsonp transmitter is called. false indicates yes. its function: the url will add a uri. query. _ ksTS = util. now () + '_' + util. guid (); that is, ksTS = timestamp _ globally unique identifier. The guid function is used to generate a globally unique identifier, which is generally called UUID or GUID. Here, url Processing is complete. It is still an object. Start! The start event has many event processors, which can be judged before execution. We hold the ype ['jsonp'] to start the jsonp. js section. Jsonp. the first thing to note in js is to copy the code IO. setupConfig ({jsonp: 'callback', jsonpCallback: function () {// do not use now (). In extreme cases, return util may be repeated. guid ('jsonp') ;}}); the Code is copied and setupConfig is called. It is clear that the function parameter name is initialized to callback. JsonpCallback is a function that initializes a globally unique identifier. The following util. guid is the Globally Unique Identifier generated. It is added after 'jsonp' as the function name. The Globally Unique Identifier can prevent this function name from being duplicated with other variables. In the callback function of the start event, the function name string is generated first, and then incorporated into uri. query c. uri. query [c. jsonp] = jsonpCallback ;. Then the function executes a series of common jsonp programs. Create a global function, bind it to the Global Object win [jsonpCallback], and clear delete win [jsonpCallback] After setting the request. It should be noted that it is bound to a global object, because the global variables declared by var cannot be cleared. Kissy used a small trick here. It created a temporary global function and gave a variable named previous. Then, when the callback function is completed after the request, win [jsonpCallback] = previous. If it is loaded successfully, previous will be executed to save the required json format data. The converter converters. script. json is defined later. Here, return response [0], the returned value has been saved response = [r] before, and [r] is the global function parameter. The converter has implemented this way! The corresponding processing mechanism throw new Error ('not call jsonpCallback: '+ jsonpCallback );. Finally, change dataType to dataType [0] = 'script'; dataType [1] = 'json'; you can easily know with comments that this is in preparation for calling the script transmitter. Conclusion: jsonp. js defines, adds the global function parameter name/value in the URL, defines, calls, and deletes the global function, and binds the script to the json converter to implement this series of behaviors and to the start event. Let's go back to base. js. The following is the preparation for sending. TransportConstructor = transports [c. dataType [0] | transports ['*']; transport = new TransportConstructor (self); before jsonp. js already knows that the script transmitter is responsible for sending the request. In fact, jsonp and getScript send requests in the same way. They dynamically load js scripts, so it is not surprising to use the script to upload scripts in a unified manner. IO. setupTransport works as early as IO. js loading *-transport. js has been completed, such as IO. setupTransport ('script', ScriptTransport); IO. setupTransport ('iframe', IframeTransport ~). Take a look at setupTransport dataType = c. dataType = util. trim (dataType | '*'). split (rspace); if (! ('Cache' in c) & util. inArray (dataType [0], ['script', 'jsonp']) {c. cache = false;} is obviously open the script-transport.js to open the first saw is still initialization. Then, determine whether the browser supports XHR2 CORS. If yes, change the sender and Ajax requests. This is not the case here. The Ajax module is a bit complicated and the detailed explanation is too long. Later, the traditional script is sent. Add the send, _ callback, and abort methods for the script sender. Send defines io. script as require. load (for usage, refer to jQuery. load), and the url is io. _ getUrlForSend (). Base. js mentioned this method in the annotation in methods. js. We will try again later. The encoding settings are followed by callback parameters in various States. _ Callback deletes io. script to prevent repeated calls, and then transmits corresponding parameters to io. _ ioReady Based on the status. Abort, as its name implies, is an interrupt function. Summary: The script-transport.js defines the sending and callback of the script transmitter. Let's look back at methods. jsmethods. js and start with handleResponseData, the response data function. Note that the replication code var prevType = dataType [0]; for (var I = 1; I <dataType. length; I ++) {type = dataType [I]; var converter = converts [prevType] & converts [prevType] [type]; if (! Converter) {throw new Error ('no covert for '+ prevType +' => '+ type);} responseData = converter (responseData); prevType = type;} io. responseData = responseData; copy the jsonp code. js finally sets ype [0] = 'script'; dataType [1] = 'json'; here the converter selects converters. script. json, and then execute the received json data to io. responseData. Here, jsonp's data processing is complete. It is not associated with the script. The script converter has also been implemented in jsonp. js. Util. extend implements IO to inherit the promise object and add some methods to the prototype. Most of them are header Processing, and we only care about _ ioReady and _ getUrlForSend. Callback function _ ioReady processes the response based on the passed status code and status text (success, error). If it succeeds, handleResponseData is called and throws the response if it fails. There is a setTimeout here, because throw e will make subsequent code unable to continue to be executed, so this problem needs to be solved asynchronously. The implementation of Ajax Timeout is also like this !). _ GetUrlForSend is to convert a url object to a url string! The url appears here! (Kissy APIDoc does not contain url. stringify. In fact, url. stringify = url. format. Do not doubt it! I specially read the util source code !). Summary: methods. js processes response data and url generation. Finally, return to base. jsyiminghe chicory and stand independently behind the flag (// flag as sendingf! L! A! G! Smile )! Then ransport. send ()! The subsequent error handling has been mentioned earlier, and is the same as _ ioReady. End. the following is a simple example of the kissy io module, which enables calls to the flickr API (this test is preferred at Home and Abroad) <script> (function () {var APIurl = 'HTTP: // api.flickr.com/services/feeds/photos_public.gne'; var onSuccess = function (data) {console. log ('get data: ', data);} require (['IO'], function (io) {IO ({url: APIurl, type: 'get', dataType: 'jsonp', jsonp: 'jsoncallback', jsonpCallback: 'ctest', data: {tags: "water", tagmode: "any", format: "json"}, c Omplete: onSuccess}) ;}) ;}() </script> copies the code and then implements the whole process of the program. Let's review the previous content and sort out the ideas. Analysis summary advantages: the combination of Chinese and English greatly enhances the readability of comments! The code structure is very clear, and reading is very smooth before and after, basically there is no obstacle. The implementation of jsonp gives priority to CORS, and the processing of callback functions is also a small highlight for me. The loading of CommonJS standardized modules is different, and it also makes module development very indirect and reflects the strong respect of node. js by the front-end chicory of Alibaba. Disadvantages: similar to util. parseJson and url. stringify, which are not mentioned in the API documentation, the source code needs to be viewed in other modules, increasing the analysis time. This is a disadvantage! We hope that kissy's chicory will improve some documents. Then there is a love English comment ~ Although it is fun ~ However, this also gives me a way to give advice to Chicory! (I found an obvious word error, and I have already reported it.) the depth of this analysis is definitely not enough, because we are a beginner in js. So I hope you will tell me what is wrong! If chicory passes by to raise some comments, it would be better. I also hope that my blog can help students who want to read the framework source code but are not afraid to move forward, with a little bit of thinking and confidence (I can see this dish! Also dare to blog !). Finally, some people guessed it was correct. This would be a series of articles!

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.