We have implemented a simple asynchronous invocation framework, yet there is some drawback, that is, sequential asynchronous functions need to be declared in a nested way.
In real-world development, it is common to perform a series of synchronous asynchronous operations sequentially. Or with the Baidu Hi Web version of the example, we have to get the contact list asynchronously, and then asynchronously get each contact's specific information, and the latter is paged get, each request sent 10 contact names and then retrieve the corresponding specific information. This is the number of asynchronous requests that require sequential execution.
To do this, we need to design a new way to optimize the readability of the code, so that the sequential asynchronous operation code looks as elegant as the traditional sequential synchronous operation code.
Traditional practices
Most programmers can have a good understanding of sequential code, such as this:
var firstResult = firstOperation(initialArgument);
var secondResult = secondOperation(firstResult);
var finalResult = thirdOperation(secondResult);
alert(finalResult);
The function that executes first provides the required data for the function that is executed later. However, after using our asynchronous invocation framework, the same logic must become this:
firstAsyncOperation(initialArgument).addCallback(function(firstResult) {
secondAsyncOperation(firstResult).addCallback(function(secondResult) {
thirdAsyncOperation(secondResult).addCallback(function(finalResult) {
alert(finalResult);
});
});
});
Chain Style
I think the code above is really too bad, and I want to be able to transform it into a jquery-style chain. To do this, we first construct a use case:
Cat.Async.Operation.go(initialArgument)
.next(firstAsyncOperation)
.next(secondAsyncOperation)
.next(thirdAsyncOperation)
.next(function(finalResult) { alert(finalResult); })
In this use case, we pass in the initialization data in the go, and then pass each next with a data processing function that processes the data sequentially.
Simultaneous coexistence
All of the above use case calls are asynchronous functions, but we'd better be able to be compatible with synchronization functions so that the user does not need to care about the implementation of the function. So let's write another use case like this:
Cat.Async.Operation.go(0)
.next(function(i) { alert(i); return i + 1; })
.next(function(i) {
alert(i);
var operation = new Cat.Async.Operation();
setTimeout(function() { operation.yield(i + 1); }, 1000);
return operation;
})
.next(function(i) { alert(i); return i + 1; })
.next(function(i) { alert(i); return i; });
In the above use cases, we expect to see a sequence of hints for 0, 1, 2, and 3, and between 1 and 2 intervals of 1000 milliseconds.