In the previous article, we designed a chained invocation for the asynchronous invocation framework to enhance the code readability of the asynchronous call queue, and now we're writing code to implement this part of the functionality.
Call Portal
A chained invocation has two entrances to the Async.go method and the Async.chain method, which are essentially consistent, except that the Async.chain method does not provide the initial parameters when invoked, and the Async.go method provides the initial parameters at the time of invocation and initiates the asynchronous call chain.
Async.chain = function() {
var chain = new Async.Operation({ chain: true });
return chain;
};
Async.go = function(initialArgument) {
return Async.chain().go(initialArgument);
}
As we can see here, the chained call itself is also a async.operation, the Go method and next method required for the chained invocation are all extensions to the async.operation, and this extension is not difficult, as described in the next section.
Extension methods
As we all know, the callback functions added through the Addcallback method are executed one at a--at least for the synchronization function, so we can maintain the asynchronous call queue with this feature of async.operation, provided we support it with queues for asynchronous calls.
For asynchronous calls to queue support, we'll deal with it later, starting with the out-of-the-box Addcallback method and the yield method to extend the Go method and next method.
this.go = function(initialArgument) {
return this.yield(initialArgument);
}
this.next = function(nextFunction) {
return this.addCallback(nextFunction);
};
In fact, the go method and next method directly call the yield method and the Addcallback method. The semantics of the Go method, like the yield method, pass a parameter to the Async.operation instance and start the call queue. Also, the semantic and Addcallback method of the next method adds a call to the end of the queue.
asynchronous queues
How do you make a queue that is supposed to support synchronization only become asynchronous? This requires the detection of the return of each call in the queue, and if the return type is async.operation, we know it is an asynchronous call, using a special method and so on before it executes.
callbackResult = callback(self.result);
self.result = callbackResult;
if (callbackResult && callbackResult instanceof Async.Operation) {
innerChain = Async.chain();
while (callbackQueue.length > 0) {
innerChain.next(callbackQueue.shift());
}
innerChain.next(function(result) {
self.result = result;
self.state = "completed";
self.completed = true;
return result;
});
callbackResult.addCallback(function(result) {
self.result = result;
innerChain.go(result);
});
}
If the call returns a Async.operation instance, we use its own Addcallback method to help us execute the remaining calls in the queue. To be exact, we construct a new call chain, transfer the rest of the queue to the new call chain, and then let the current asynchronous call start the new call chain in the callback.
There are also places where we need to make a few modifications to accommodate the new asynchronous call queue. For example, the state change of result, States, and completed is different in chained calls.