The original link: http://chriscindy.top/post/the-analysis-of-the-source-code-of-co/

Co is an open source project launched by the famous TJ in 2013, which uses ES6 Generator functions to solve asynchronous operations. It is also the precursor of async/await, the ultimate solution of JavaScript asynchronous operations. Today, the CO version is 4.x, but the code is still a few hundred lines long and easy to read and learn. Let’s take a look at how CO handles asynchronous operations. First, let’s look at the basic usage of CO. Co is easy to use. You can write asynchronous code in co() as synchronous code by passing a Generator function as an argument. Take a look at the official example:



In the function body on line 9, the values of a, b, and c are returned asynchronously, but can be called synchronously. This is the magic of CO.

In addition, CO provides an API —co.wrap()To convert a generator function wrapped in CO into a generic function that returns a promise, as shown in the following example:

Now that we know about the API, we can take a look at the internal implementation of CO. Below is the source code annotated by the author (Chinese annotation) :









As we can see, the core logic of CO is next function in line 90. Here, the return value of each yield is wrapped as a Promise object, and next function is recursively called in the onFulfilled and onRejected states of the Promise. Chain calls are guaranteed to execute automatically, enabling asynchronous code to run synchronously.

You may also wonder if such chained auto-execution is possible without Promise. In fact, prior to the 4.0.0 release of CO, the underlying implementation used the Thunk function instead of Promise. Interested readers can switch to version 3.1.0 to learn the source code.

Note: For questions about what a Thunk function is, click here.

Ruan Yifeng has a precise conclusion about the principle of automatic execution of Generator functions in His book Introduction to ECMAScript 6: “The key to automatic execution is that there must be a mechanism to automatically control the flow of Generator functions and to receive and return execution rights of programs. Callbacks can do that, and so can Promise objects.” Let’s use the Promise object as an example: Keep the value returned by yield as a Promise object, and execute it to give the program execution rights. The program execution authority can then be returned by calling Generator’s next method in the promise. then and promise. reject methods. This results in automatic execution of the generator function.

Finally, thanks to excellent projects like CO as trailblazers, we have the future async/await, and JavaScript developers are no longer stuck with asynchronous programming because of the unique single-threaded nature of the language.