Question and answer form read jquery source (iii)

Source: Internet
Author: User
Tags new set string to json

Through Alan's blog, we can see that jquery's promise and other callbacks are implemented through Jquery.callbacks. So let's take a quick look at jquery.deferred and jquery.callbacks. Take a look at some of their questions.

Question: Why is the configuration of jquery.callbacks a string parameter?

Jquery.callbacks has four kinds of configuration, namely once, memory, unique, Stoponfalse. The configuration of jquery.callbacks is different from what we used to know, not using JSON, but using strings as a form of configuration.

A: The configuration of jquery.callbacks is really weird, jquery.callbacks used a createoptions function to convert the string to JSON.

var rnotwhite = (/\s+/g); function createoptions (options) {    var object = {};     function (_, flag) {        true;    });     return object;}

such as "Once memory unique" string, will eventually be converted to {"Once": true, "Memory": true, "unique": true}. But I want to ask why not use JSON directly?

Like this use of string configuration, JavaScript is also available, the regular expression in JS is this configuration form.

Such as:

var New REGEXP ("E", "GIM");

The "GIM" here is the configuration item. However, this configuration method is difficult to understand, this does not conform to the concept of jquery, so I think jquery.callbacks using string configuration instead of array configuration is a failure in jquery.

Question: Is the jquery.deferred encapsulated function necessarily asynchronous?

Answer: This is a question that I have been puzzled about before. Let's jump out of jquery and use standard JavaScript first to see if his async function is necessarily asynchronous.

The test code is as follows:

SetTimeout (function() {    Console.log (0);},0); setTimeout (function  () {    console.log (1);},0);

Console.log (2);

Very simple line of code, we are also very clear that the output is "201". JavaScript is a single-threaded execution, so callbacks for asynchronous functions are executed behind. Simultaneous asynchronous callback functions are placed into the queue, so they are executed in the order in which they are queued. Note that the time parameter of the settimeout must be given 0, because the settimeout callback time default value is not necessarily 0.

We remove the settimeout of the middle Output 1 function so that it is no longer asynchronous.

SetTimeout (function() {    Console.log (0);},0); Console.log (1); Console.log (2);

The result becomes "120". The results do not need to be illustrated, but only for comparison purposes.

Now the transposition uses the syntax of the async function, wrapping the output 1 part with the ES7 async function:

function Test () {  console.log (1);} SetTimeout (function() {  Console.log (0);},0 // Note that the test does not give an await decoration, otherwise the log (2) must be executed after test
Console.log (2);

The result is "120".

We then convert the asynchronous function to promise.

SetTimeout (function () {
Console.log (0);
},0);
New Promise (function (resolve) {
Console.log (1)
Resolve ();
})
Console.log (2);

The code above should be the same as the asynchronous function result, and the result is exactly the same, with the result "120".

From these examples we can see that using promise encapsulated functions (asynchronous functions), if their contents are not asynchronous, promise performs the same behavior as non-async functions. This shows that the asynchronous function is good or promise, only changes the callback mode, and does not change the execution order. If you use an asynchronous function to encapsulate a non-asynchronous function, the callback method changes, but the callback part does not "execute asynchronously".

Therefore, the jquery.deferred encapsulated function should also have such behavior.

SetTimeout (function() {Console.log (0);},0); $. Deferred (). Resolve (). Then (function() {    console.log (1);}); Console.log (2);

The results above are also "120".

We can also look at the jquery.callbacks source, which contains no settimeout, or other can return asynchronous callbacks. so asynchronous functions are good, promise or jquery.deferred, and all they change is the way of callbacks. However, this is the result of jQuery2.0, jQuery3.0 the result is "201", if you are interested, you can try it yourself.

Question: What does this point in the callback for Jquery.callbacks?

A: Simple analysis of the source code structure:

Jquery.callbacks =function(options) {varList = []; varFire =function() {list[firingindex].apply (memory[0], memory[1 ] ) ; }        return{add:function() {            ( functionAdd (args) {Jquery.each (args,function(_, Arg) {List.push (ARG);            } );                            }) (arguments); return  This; }, Firewith:function(context, args) {args= [Context, Args.slice?]args.slice (): args];            Queue.push (args); if( !firing)            {Fire (); }                        return  This; }, Fire:function() {Self.firewith ( This, arguments); return  This; },    };};

From this code it is clear that by adding we will save the function in the internal private variable list, and then use the Apply call. The external exposure functions are firewith and fire. The context parameter of Firewith is finally passed to apply, So this is the context in our callback. The fire function calls the Firewith and passes it itself, so this is the callbacks object in the callback function .

Question: What does this point in the callback for jquery.deferred?

A: This in the standard promise is a pointer to the global scope, such as window.

var New Promise ((r) ={R ()}) D.then (function() {Console.log (This)})  // Note, Not available here () =>{console.log (This)}

The output is window, which proves our previous statement.

Let's take a look at Jquery.deferred's schematic source code:

jquery.extend ({Deferred:function(func) {vartuples = [                [ "Resolve", "done", Jquery.callbacks ("Once Memory"), "resolved" ],                [ "Reject", "fail", Jquery.callbacks ("Once Memory"), "rejected" ],                [ "Notify", "Progress", Jquery.callbacks ("Memory"] ], state= "Pending", Promise={then:function(/*Fndone, Fnfail, fnprogress*/ ) {                    varFNS =arguments; returnJquery.deferred (function(Newdefer) {Jquery.each (tuples,function(i, tuple) {varfn = jquery.isfunction (fns[i]) &&fns[i]; //deferred[Done | fail | progress] for forwarding actions to Newdeferdeferred[tuple[1] (function() {                                varreturned = FN && fn.apply ( This, arguments); if(Returned &&jquery.isfunction (returned.promise)) {returned.promise (). Progress (Newdefer.notify ). Done (Newdefer.resolve). Fail (Newdefer.                                Reject); } Else{newdefer[tuple[0] + "with" ](                                         This= = = Promise? Newdefer.promise (): This, FN?[returned]: arguments);                        }                            } );                        } ); FNS=NULL;                }). Promise (); }, Promise:function(obj) {returnObj! =NULL?jquery.extend (obj, Promise): promise; }}, Deferred= {}; Jquery.each (tuples,function(i, tuple) {varList = tuple[2], statestring= tuple[3 ]; promise[tuple[1]] =List.add; if(statestring) {List.add (function() { state=statestring; }, tuples[I^ 1] [2].disable, tuples[2] [2].lock); } deferred[tuple[0]] =function() {deferred[tuple[0] + "with"] ( This= = = Deferred? Promise: This, arguments); return  This;            }; deferred[tuple[0] + "with"] =List.firewith;        } );        Promise.promise (deferred); if(func) {Func.call (deferred, deferred); }        returndeferred; }} );

Two objects--deferred and promise are built in the code. Deferred is equivalent to encapsulation of asynchronous processes, while promise is the encapsulation of the promise model. At the end of the code, the promise is woven into the deferred.

Resolve, Reject, notify is the promise of the three sets of state functions, in fact, the execution strategy of the three functions are similar, so jquery adopts the policy model, with a two-dimensional array tuples the 3 strategies are encapsulated together.

In the lower part of the code, we can see that jquery implements the three functions of promise done, fail, progress, and the three functions are tuples jQuery.Callbacks.add. The deferred extends six functions--resolve, Reject, notify and Resolvewith, Rejectwith, Notifywith, and the first three functions are encapsulated for the last three functions. The latter three functions are encapsulated in the JQuery.Callbacks.fireWith. When the first three functions call the last three functions, the context parameter is the promise of the pass (unless the callback function is changed by bind, Reject, resolve). So when deferred executes resolve, Reject, notify, this is the promise object of the callback function, and when this is used Resolvewith, Rejectwith, Notifywith, or bind, Call, apply changes the execution context of resolve, reject, notify, and this of the callback is a pointer to the given object.

Again, the definition of the top then method is the same as traversing tuples. The tuples array defines the three function names of done, fail, progress, and the three parameters (done, catch, notify) that are the same as then, and these three parameters are callback functions. The way to callback them is deferred's done, fail, progress three functions, we know that these three functions are used promise to weave in, the real method is promise resolve, reject, notify these three functions, Thus the this of the callbacks in then also points to the promise or the previously specified context.

This point to promise actually does not have much meaning, but through the Xxxwith function or with BIND, call, apply change Resolve, Reject, notify the way of the context, is the highlight of jquery. The purpose of jquery is to provide such an API so that we can specify the promise this, which seems more flexible and more convenient for us to manipulate callbacks.

However, the different of this in the callback is a big difference between the jquery.deferred and the standard promise, which is not standard usage, which must be remembered. Although the API provided by jquery is convenient, it is not recommended to change the column promise model, especially if promise is now in ES6 syntax, and ES7 's asynchronous syntax is also based on promise, Creating standard promise on browsers that do not support promise is what jquery should do, because it is the only way to achieve promise syntax docking.

Question: Why weave promise into the deferred?

A: According to the jquery idea, deferred is equivalent to the encapsulation of the asynchronous process, is the creator and conductor of the promise, but according to the idea of jquery, the two can better simplify the asynchronous object model, such as:

var d = $. Deferred ();d. Resolve ();d. Promise (). Then (()={...    }) // is equivalent to var d = $. Deferred ();d. Resolve (). Then (()={...    })

Is the wording below more simple and compact? It also complies with jquery's chained operations. To put it simply, it is easier to understand the concept of an object that is less.

In fact, promise can also be woven into other objects, such as:

var d = $. Deferred ();d. Resolve ();d. Promise (MYOBJ), Myobj.then (()={...     })

In this way, jquery can be very flexible to embed promise operations into any object, very convenient.

Question: JQuery.Deferred.promise () Have you implemented promises/a+?

A: Yes, this does not need to see the source code, just look at the API is also very clear,jQuery.Deferred.promise () did not implement promises/a+. For example, jquery adds done, fail, progress functions, these three functions are not promises/a+ model standard function name, but it is similar to the implementation of promises/a+ conceptual model. At the same time, promises/a+ has catch function, but jquery is not implemented, the main reason is that catch is the key word in the early IE browser, so use fail instead. Done, progress is an extension of jquery according to its own needs.

Another important difference between jQuery.Deferred.promise and promises/a+ is the handling of exceptions . The instance code is as follows:

New Promise ((Resolve) ={resolve ()}) D.then (()=>{throw "error"}). Catch ((e) =>{alert (e)})

The standard promise pops up the alert box for the error word.

Re-transposition JQuery.Deferred.promise test:

$. Deferred (). Resolve (). Then (() =>{throw "error"}). Fail ((e) =>{alert (e)})

Results direct error, and there is no popup alret box.

jquery in the source code does not have an exception to the callback call, so the callback exception cannot be automatically returned to the rejected promise. This difference makes the exception handling of jquery.deferred very inflexible and needs to be done manually. Modified to:

$. Deferred (). Resolve (). Then (()={    try{        throw "error"     }catch(e) {        return  $. Deferred (). Reject (E);    }}). Fail ((e)+ ={    alert (e)}        )

This will bring up the alert box for the error word.

Question: Can JQuery.Deferred.promise () and the browser's promise call each other?

A: Of course not directly call, need to do the conversion, the conversion code here does not demonstrate. The reason why you cannot call directly is that JQuery.Deferred.promise does not implement promises/a+. But this is only part of the reason, the biggest reason is the historical problem, jQuery2.0 time, the browser's promise model has not been established, so it is impossible to consider the browser promise with each other to invoke the problem.

Question: What improvements do jQuery.Deferred.promise need to make if you want JQuery.Deferred.promise () to be able to be called directly from the browser's promise?

A: First of all, to achieve a complete implementation of promises/a+, remove jquery personalized things, such as Xxxwith call, deferred instead of promise, done and other nonstandard functions named. Therefore, in the JQuery3 jquery.deferred did not upgrade the adjustment, the new jQuery.Deferred.promise provides a new set of APIs, fully implement the promises/a+ specification, And can invoke the browser's promise to call each other .

Question and answer form read jquery source (iii)

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.