preface
Learning without thought is labor lost
Recently I have been reading some excellent NPM package code, the cause is that I feel that the code is not standard enough, not concise enough.
But I do not know what kind of code is a better code, after some thinking I think or to stand on the shoulders of giants.
Read good source code and learn how to write enjoyable code and then write a chapter summary to sort out the whole learning process and share it with others.
Why write so much at the beginning? Because I needed a reason to keep going. So I can ride the waves and move forward.
Without further ado, start summing up.
Evolution of JS asynchronous programming
Callback hell phase
Before we formally introduce await-to-js, let’s briefly review the evolution of asynchronous programming in JavaScript. Asynchronous programming was a big problem for front-end engineers before Promises came along, and their predecessors would have seen code like this a lot.
function AsyncTask() {
asyncFuncA(function(err, resultA){
if(err) return cb(err);
asyncFuncB(function(err, resultB){
if(err) return cb(err);
asyncFuncC(function(err, resultC){
if(err) return cb(err);
// And so it goes....
});
});
});
}
Copy the code
This code, which has callbacks nested in both vertical and horizontal callbacks, is also known as callback hell. You can see how disgusting it is, specifically with the following downsides
- Difficult to maintain (don’t want to look at, but also maintain a **)
- Difficult to catch errors (one at a time?)
All in all, this was a problem that needed to be addressed at the time, so in ES6, there were promises.
Promise phase
Promise is an elegant asynchronous programming solution. Syntactically, it is an object that represents the final completion or failure of an asynchronous operation. Semantics, it is a promise that promises you a result over time.
Since its prototype then,catch,finally returns a new promise, it allows us to make chain calls, solving the problem of traditional callback hell.
Because it has an all method, it can support multiple concurrent requests and retrieve data from concurrent requests.
With promises in place, the code above can be written as follows.
function asyncTask(cb) {
asyncFuncA.then(AsyncFuncB)
.then(AsyncFuncC)
.then(AsyncFuncD)
.then(data => cb(null, data)
.catch(err => cb(err));
}
Copy the code
In contrast to the callback hell above, using promises helps us keep our code vertical only and provides callbacks to handle errors. Definitely a lot more elegant. But as good as promises are, there are still two things that fall short of each
- Not synchronized enough (code still extends vertically)
- You cannot error handle every asynchronous operation
This is why ES7 has async/await as the last solution to asynchronous programming.
async/await
Async functions are syntactic sugar for Generator functions. Async is represented with the keyword async and await is used inside the function. Compared to Generator, async functions are improved in the following four aspects:
- Built-in actuator.
Generator
The execution of a function must depend on the executor, andasync
The function has its own executor, which is called in the same way as ordinary functions - Better semantics.
async
和await
In contrast to*
和yield
More semantic - Wider applicability.
co
Module convention,yield
A command can only be followed by a Thunk function or a Promise object. whileasync
Function of theawait
The command can be followed by a Promise or a value of primitive type (Number, string, Boolean, but this is equivalent to a synchronous operation) - The return value is Promise.
async
The return value is a Promise object, which is more convenient than the Iterator returned by Generator functions and can be used directlythen()
Method to call
Understand async/await
With async/await, the above code can be rewritten as follows
function async asyncTask(cb) {
const asyncFuncARes = await asyncFuncA()
const asyncFuncBRes = await asyncFuncB(asyncFuncARes)
const asyncFuncCRes = await asyncFuncC(asyncFuncBRes)
}
Copy the code
We can also do error handling for each asynchronous operation
function async asyncTask(cb) { try { const asyncFuncARes = await asyncFuncA() } catch(error) { return new Error(error) } try { const asyncFuncBRes = await asyncFuncB(asyncFuncARes) } catch(error) { return new Error(error) } try { const asyncFuncCRes = await asyncFuncC(asyncFuncBRes) } catch(error) { return new Error(error) } }Copy the code
Are the two shortcomings of each of the above promises optimized? Therefore, async/await is the last solution of ASYNCHRONOUS WRITING in JS. I personally think there is no problem, but I wonder if you have seen the above code. Is it not convenient or intelligent to use try/catch for error handling for every asynchronous operation?
Await-to-js – small and beautiful NPM package
Basic usage
This is how the author introduces the library
Async await wrapper for easy error handling without try-catch.
The Chinese translation is
Asynchronous wait wrappers that easily handle errors without a try-catch.
To make a simple comparison, here’s how we handled errors in asynchronous operations
function async asyncTask() {
try {
const asyncFuncARes = await asyncFuncA()
} catch(error) {
return new Error(error)
}
try {
const asyncFuncBRes = await asyncFuncB(asyncFuncARes)
} catch(error) {
return new Error(error)
}
try {
const asyncFuncCRes = await asyncFuncC(asyncFuncBRes)
} catch(error) {
return new Error(error)
}
}
Copy the code
With await-to-js, we can handle errors like this
import to from './to.js';
function async asyncTask() {
const [err, asyncFuncARes] = await to(asyncFuncA())
if(err) throw new (error);
const [err, asyncFuncBRes] = await tp(asyncFuncB(asyncFuncARes))
if(err) throw new (error);
const [err, asyncFuncCRes] = await to(asyncFuncC(asyncFuncBRes)
if(err) throw new (error);
}
Copy the code
Isn’t it much simpler?
What dark magic did the author use?
It may surprise you, but the source code is only 15 lines long.
Source code analysis
export function to<T, U = Error> ( promise: Promise<T>, errorExt? : object ): Promise<[U, undefined] | [null, T]> { return promise .then<[null, T]>((data: T) => [null, data]) .catch<[U, undefined]>((err: U) => { if (errorExt) { const parsedError = Object.assign({}, err, errorExt); return [parsedError, undefined]; } return [err, undefined]; }); } export default to;Copy the code
Above here is TS version of the source, but considering that some students may not have contact with TS, I focus on the following version of the JS version of the source.
export function to(promise, errorExt) {
return promise
.then((data) => [null, data])
.catch((err) => {
if (errorExt) {
const parsedError = Object.assign({}, err, errorExt);
return [parsedError, undefined];
}
return [err, undefined];
});
}
export default to;
Copy the code
Let’s get rid of the errorExt custom error text here. The core code looks like this
export function to(promise) { return promise .then((data) => [null, Data]). Catch ((err) => {return [err, undefined]; }); } export default to;Copy the code
As you can see, the logic of the code in Chinese looks like this
- Either success or failure returns an array, the first item of which is associated with the error, and the second item of which is associated with the outcome
- On success, the first item of the array, the error message, is empty, and the second item of the array, the response, is returned normally
- If it fails, the first item in the array, which is the error message, is the error message, and the second item in the array, which is the response result, returns undefined
After the above analysis we can determine that there is no black magic in the world, there is no you can not do, only you can not think.
Assign (errorExt); assign (errorExt); assign (errorExt); assign (errorExt); assign (errorExt)
conclusion
Source code is not terrible, terrible is their fear in the face of the unknown.
Dare to face, dare to try, to the next level.
Keep it up, kid.
Follow me, VX: Codebangbang, Nuggets: Love hei hei.
The resources
- Warehouse address: github.com/scopsy/awai…
- How to write async await without try-catch blocks in Javascript