As Async/Await is officially incorporated into ES7 standard, more and more people are using this so-called asynchronous programming end level solution. However, the more await expressions are found in the process of use, the more redundant code is used to create Promise objects, and the sense of elegance plummets. For this reason, this paper combines Decorator to realize more elegant asynchronous programming.
- Declare an asynchronous function through async keyword;
- The await keyword is only valid in async functions and expects a Promise object. The await expression pauses the execution of the current async function, waiting for Promise to finish processing and return the result.
Example:
class Action { step_1(value){ return new Promise((resolve, reject) => { // Return Promise object console.log('[step_1]', value); resolve(); }); } step_2(value){ return new Promise((resolve, reject) => { console.log('[step_2]', value); resolve(); }); } step_n(value){ return new Promise((resolve, reject) => { console.log('[step_n]', value); resolve(); }); } } // async self executing function (async ()=>{ let action = new Action(); await action.step_1('one'); // => [step_1] one await action.step_2('two'); // => [step_2] two await action.step_n('next'); // => [step_n] next })();Improvement
As you can see above, each step method needs to return a Promise object and execute asynchronous code in the Promise callback function.
However, such a way of writing is not elegant at all, and the more await expressions, the more code to create Promise objects, which is very redundant.
Decorator
Decorator can annotate and modify classes or properties.
With this feature, the redundant code for creating Promise object can be encapsulated as a decorator and applied to step method.
/** * Decorator: Promise * @param target - Decorated class * @param property - Attribute name * @param descriptor - property descriptor * @author Brother range < [email protected] > */ function promisify(target, property, descriptor){ descriptor.value = new Proxy(descriptor.value, { // Intercept function calls apply(method, context, argList){ // Returns a new Promise object return new Promise((resolve, reject) => { // Call the original function and inject resolve and reject return Reflect.call(method, context, resolve, reject, ...argList); }); } }); return descriptor; }
(Note: Decorator has not been included in the ECMAScript standard, but syntax support can be provided through the Babel compiler.)
Code optimization
class Action { @promisify step_1(resolve, reject, value){ console.log('[step_1]', value); resolve(); } @promisify step_2(resolve, reject, value){ console.log('[step_2]', value); resolve(); } @promisify step_n(resolve, reject, value){ console.log('[step_n]', value); resolve(); } }
(Note: due to function declaration promotion, Decorator can only be used for classes and methods.)