Class structure
First, let's build a shelf and list all the variables that need to be used. We need an array to hold the list of callback functions, a flag bit to indicate whether the asynchronous operation is complete, or to learn IAsyncResult, plus a state that allows the performer of the asynchronous operation to expose the custom execution status externally, and a variable to save the asynchronous operation result.
Copy Code code as follows:
Async = {
Operation: {
var callbackqueue = [];
This.result = undefined;
This.state = "Waiting";
this.completed = false;
}
}
Addcallback Method
Next, we want to implement the Addcallback method, its job is very simple, is to put the callback function in the Callbackqueue. Also, if the completed is true at this time, the asynchronous operation has been yield, this callback is called immediately.
Copy Code code as follows:
This.yield = function (callback) {
Callbackqueue.push (callback);
if (this.completed) {
This.yield (This.result);
}
return this;
}
Let's assume that the yield method pulls the callback function in the Callbackqueue one at a time and then calls it, so if compeleted is true, then the yield is OK with the existing result again, This yield naturally invokes the callback function that was added to the callbackqueue.
As for the final return of this; In order to facilitate the jquery style of chain writing, you can add multiple callback functions consecutively through a dot-number separation:
Copy Code code as follows:
AsyncOperation (argument)
. Addcallback (Firstcallback)
. Addcallback (Secondcallback);
Yield Method
Finally, we will implement the yield method. It needs to remove the callback function in the Callbackqueue, and then call it all over again, and make sure the operation is asynchronous.
Copy Code code as follows:
This.yield = function (Result) {
var self = this;
settimeout (function () {
Self.result = result;
Self.state = "Completed";
Self.completed = true;
while (Callbackqueue.length > 0) {
var callback = Callbackqueue.shift ();
Callback (Self.result);
}
}, 1);
return this;
}
By using settimeout, we ensure that the actual operation of the yield is done asynchronously. We then update the results of the user's incoming yield and the related state to the object properties, and then traverse Callbackqueue to invoke all the callback functions.
Summary
So we do a simple JavaScript asynchronous invocation framework, the complete code can look here: Asynchronous call frame Async.operation.
This framework is a good solution to the occurrence of synchronous asynchronous operation in the call stack, assuming that all functions return async.operation, the user of the framework can use a unified pattern to write code, processing function return, regardless of whether the function is actually synchronous return or asynchronous return.
For a serial invocation of multiple asynchronous functions, we can now write in a nested addcallback way, but as the number of nesting layers increases, the code becomes more and more unattractive:
Copy Code code as follows:
Firstasyncoperation (). Addcallback (function () {
Secondasyncoperation (). Addcallback (function () {
Thirdasyncoperation (). Addcallback (function () {
Finalsyncoperation ();
});
});
});
Can we change the nested form into a jquery-style chain? That's the next thing we're going to think about, if you don't want to miss the discussion.