From the whole point of view, the implementation of Q is actually a closure of the application, the following simple explanation of the basic function of Q.
GitHub Q's API
Realize the function of Q, first understand the API of Q
The documentation for the simplest part of the https://github.com/kriskowal/q interception is as follows:
var deferred = Q.defer();FS.readFile("foo.txt""utf-8"function (error, text) { if (error) { deferred.reject(newError(error)); else { deferred.resolve(text); }});return deferred.promise;
You can see that the key API has,,, and defer
reject
then the promiss
resolve
document also involves the value of the results, and the error captures, including,, are then
catch
done
no longer posted.
Entrance
Start with the top four APIs first. Through the first line of code
var deferred = Q.defer();
Then the obvious code is:
var Q = { function(){}}
defer()
The return value then deffred
has 3 properties.
var Q = { function(){ return { function(error){}, function(data){}, null//当前还不能确定是个什么值 } }}
The above basic code structure comes out. In order to supplement the content of Promiss.
Promiss
Ask for convenient explanation, here first preset a use environment. Derive the code implementation from the results.
varAdd = function(){ vardeferred = Q.defer () setTimeout ( function(){Deferred.resolve (2) }, -)returnDeferred.promise} Add (). Then ( function(data){Console.log (data)returnData +1}). Then ( function(data){Console.log (data)}). Then ( function(data){ Throw New Error()}). catch ( function(err){ if(ERR) {Console.log ("There is a error!") Console.log (Err)}})
You can see that the above add is using the Q. Look first.
add().then(...).then(...).catch(...)
Then it is clear that deffred.promiss
there are at least three attributes (Then,catch two plus no-show-done), and that two of them should return the original object. So get
var Q = { function(){ var promiss = { function(fn){ //接收回调函数做为参数 ... do something return promiss }, function(fn){ //... do something return promss }, function(){} } return { function(error){}, function(data){}, promiss: promiss } }}
So above, the basic object structure of the whole Q comes out. Although not implemented.
Then the implementation
varfunction(){ var deferred = Q.defer() setTimeout(function(){ deferred.resolve(2) 2000) return deferred.promise }
The above code finds that the computed result is asynchronously stored, then the function inside then should be executed when the result is calculated. As follows
var Q = { function(){ var promiss = { function(fn){ //接收回调函数做为参数 ... do something return promiss //将自身对象返回很容易做到链式调用 }, ... } return { promiss: promiss ... } }}
So
add() 返回值-> promissadd().then() 返回值-> promiss
Next, look at the data transfer. After the asynchronous resolve function gets called, obtains the actual result, this actual return value needs to give then inside the callback function. This cannot be done by directly invoking then to pass the data. Therefore, an intermediate handler function is required. As follows:
var Q = { function(){ //定义一个结果处理函数。 function(data){ //do some thing }; var promiss = { function(fn){ //接收回调函数做为参数 ... do something return promiss //将自身对象返回很容易做到链式调用 }, ... } return { function(data){ callResult(data) } ... } }}
To do the key points here, there are two issues to solve, 1. How do I pass the result to the then callback when the resolve function is called, and let it execute? How does the return value of 2.then need to be given next then?
The implementation of closures is here. The main function of closures is to isolate scopes and look for variables in the upper context.
To resolve the key, use a queue to store all the callbacks that were then, execute all the functions in the queue when the resolve executes, and loop the return value.
The following is the complete code.
varQ = {defer: function(){' use strict ' //Normal result set varResultqueue = [];//error handling handle varErrorhandle = function(Error){};varPromise = {then: function(FN){ //Store each then callback function for uniform processingResultqueue.push (FN)returnPromise}, Done: function(){ return{Catch: Promise.catch}},Catch: function(FN){Errorhandle = fn}}varCallallresultqueue = function(data){ for(vari =0; i < resultqueue.length; i++) {data = Resultqueue[i] (data); } }return{resolve: function(data){ //resolve triggers execution of all then callback functions. Callallresultqueue (data)}, Reject: function(Error){Errorhandle (Error)} Promise:promise}}}varAdd = function(){ vardeferred = Q.defer () setTimeout ( function(){Deferred.resolve (2) }, -)returnDeferred.promise} Add (). Then ( function(data){Console.log (data)returnData +1}). Then ( function(data){Console.log (data)}). Then ( function(data){ Throw New Error()}). catch ( function(err){ if(ERR) {Console.log ("There is a error!") Console.log (Err)}})
Elementary Introduction to the basic realization of Q