Async function
The title | content |
---|---|
The introduction of the async | AsyncFunction Constructor,Generator |
The meaning of async | What is async function? |
The characteristics of the async | Built-in actuators, better semantics, wider applicability, return value isPromise |
The implementation principle of Async | Generator Function, the autoexecutor |
The introduction of the async
- The ES2017 standard was introduced
async
Function to make asynchronous operations easier. Or you could sayGenerator
Grammar sugar.
AsyncFunction constructor
AsyncFunction
The constructor is used to create a newAn asynchronous functionObject, every asynchronous function in JavaScriptAsyncFunction
The object.
async function asyncFunction(){}
asyncFunction.constructor
// AsyncFunction() { [native code] }
Copy the code
- Pay attention to:
AsyncFunction
It is not a global object and needs to be retrieved as follows:
Object.getPrototypeOf(async function(){}).constructor
// AsyncFunction() { [native code] }
Copy the code
AsyncFunction grammar
new AsyncFunction([arg1[, arg2[, ...argN]],] functionBody)
Copy the code
AsyncFunction parameters
-
arg1, arg2, … ArgN: The parameter names of the function, which are one or more comma-separated strings that conform to the JavaScript identifier specification. Such as x, theValue or a, b.
-
FunctionBody: A string of JavaScript statements that form the definition of a new function.
function resolveAfter2Seconds(x) {
return new Promise(resolve= > {
setTimeout(() = > {
resolve(x);
}, 2000);
});
}
var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
var a = new AsyncFunction('a'.'b'.'return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b); ');
a(10.20).then(v= > {
console.log(v); Print 30 after 4 seconds
});
Copy the code
- perform
AsyncFunction
Constructor, one is createdAn asynchronous functionObject. But it’s better to do it firstAsynchronous function expressionDefine an asynchronous function and then call it to create itAn asynchronous functionObjects come efficiently because in the second wayAsynchronous functions are parsed by the interpreter along with other codeAnd the first wayThe function body is parsed separately. - Passed to the
AsyncFunction
constructionalAll the parametersWill becomeA variable in a new function.Variables are named and defined in the same order as parameters. - Pay attention toUse:
AsyncFunction
ConstructorAn asynchronous functionWill not be inCreate closures in the current context, itsThe scope is always global. Therefore, it can only be accessed at runtimeTheir own local variablesandThe global variable, butCannot access a variable in the scope from which the constructor is called. That is with iteval
Different places (eval
Functions are best never used.
/ * * *@description Own local and global variables */
function resolveAfter2Seconds(x) {
return new Promise(resolve= > {
setTimeout(() = > {
resolve(x);
}, 2000); })}var c = 1;
var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
var a = new AsyncFunction('a'.'b'.'c'.'return await resolveAfter2Seconds(a) + await resolveAfter2Seconds(b) + await resolveAfter2Seconds(c); ');
a(10.20, c).then(v= > {
console.log(v);
})
Copy the code
/ * * *@description Advice: Never use eval */
function test() {
var x = 2, y = 4;
console.log(eval('x + y')); // Call directly, using local scope, resulting in 6
var geval = eval; // equivalent to calling in global scope
console.log(geval('x + y')); Throws ReferenceError because 'x' is not defined
(0.eval) ('x + y'); // Another example of an indirect call
}
Copy the code
- call
AsyncFunction
Constructor can be omittednew
The effect is the same.
Async function
- Async functions are used
async
Keyword declaration function. Async functions are instances of the AsyncFunction constructor and are allowed in themawait
The keyword. - The async and await keywords allow us to write based in a more concise way
Promise
Asynchronous behavior without the need for intentional chain callspromise
.
function resolveAfter2Seconds() {
return new Promise(resolve= > {
setTimeout(() = > {
resolve('resolved');
}, 2000);
});
}
async function asyncCall() {
console.log('calling');
const result = await resolveAfter2Seconds();
console.log(result);
}
aysncCall();// Calling 2 seconds and resolved
Copy the code
Syntax of async functions
async function name([param[, param[, ... param]]]) {
statements
}
Copy the code
Parameter of async function
name
: Function name.param
: The name of the argument to be passed to the function.statements
: An expression containing the body of a function. You can useawait
Mechanism.
The return value
- a
Promise
thepromise
Or it will pass through aasync
The value returned by the function is resolved, either by a value fromasync
An exception thrown (or not caught) by a function is rejected.
async function foo() {
return 1
}
/ / equivalent to the
function foo() {
return Promise.resolve(1)}Copy the code
async function foo() {
await 1
}
/ / equivalent to the
function foo() {
return Promise.resolve(1).then(() = > undefined)}Copy the code
The meaning of async
- The body of an async function can be thought of as being separated by zero or more await expressions. The first line of code up to (and including) the first await expression (if any) is run synchronously. In this case, an async function with no await expression will run synchronously. However, an async function must be executed asynchronously if the function body has an await expression.
// The promise chain is not built in one go. Instead, the promise chain is built in stages, so care must be taken with error functions when handling asynchronous functions
async function foo() {
const result1 = await new Promise((resolve) = > setTimeout(() = > resolve('1')))
const result2 = await new Promise((resolve) = > setTimeout(() = > resolve('2')))
}
foo()
Copy the code
-
The order of execution above:
-
- The first line of the foo function will be executed synchronously and await the end of the promise. It then suspends the process that passes through Foo and gives control back to the function that called foo.
-
- After a while, when the first promise ends, control reverts back to foo. The example will
1
(the promise state is fulfilled) is returned as the result to the left of the await expression, i.eresult1
. The function will then continue, reaching the second await area, at which point the process of foo will be suspended again.
- After a while, when the first promise ends, control reverts back to foo. The example will
-
- And after a while, when the second promise ends,
result2
Will be assigned to2
After that, the function will execute synchronously and will return by defaultundefined
.
- And after a while, when the second promise ends,
// A. Catch handler is configured on the Promise chain to throw unhandled Promise errors. This is because the result returned by P2 will not be processed with await
async function foo() {
const p1 = new Promise((resolve) = > setTimeout(() = > resolve('1'), 1000))
const p2 = new Promise((_,reject) = > setTimeout(() = > reject('2'), 500))
const results = [await p1, await p2] // Not recommended. Use promise.all or promise.allSettled
}
foo().catch(() = > {}) // Catch all errors...
Copy the code
// Function declaration
async function foo() {};
// Function expression
const foo = async function () {};
// Object method
let obj = { async foo(){}}; obj.foo().then(...)// Class method
class Storage {
constructor() {
this.cachePromise = caches.open('avatars');
}
async getAvatar(name) {
const cache = await this.cachePromise;
return cache.match(`/avatars/${name}.jpg`); }}const storage = new Storage();
storage.getAvatar('jack').then(...) ;// Arrow function
const foo = async() = > {};Copy the code
The characteristics of the async
Built-in actuator
Generator
Function execution must depend on the executor, hence the existence ofco
Module, while async functionBuilt-in actuator. In other words, async functions are executed exactly like normal functions, with only one line.
const asyncFunction = async function () {
const f1 = await 1
const f2 = await 2
console.log(f1.toString());
console.log(f2.toString());
};
asyncFunction();
/ / 1
/ / 2
Copy the code
- The above code calls
asyncFunction
Function, which will then automatically execute and output the final result. It doesn’t look like anythingGenerator
Function, need to be callednext
Method, or useco
Module, can really execute, get the final result.
var gen = function* () {
var f1 = yield 1
var f2 = yield 2
console.log(f1.toString())
console.log(f2.toString())
}
var co = require('co'); // Generatir direct execution requires the CO module
co(gen).then(function() {
console.log('Generator function completed execution ');
});
/ / 1
/ / 2
// The Generator function is complete
Copy the code
Better semantics
async
andawait
Compared toThe asteriskandyield
The semantics are clearer.async
It means that there are asynchronous operations in the function,await
Indicates that the following expression needs to wait for the result.
const asyncFunction = async function() {
const f1 = await 1 // The following expression waits for the result
const f2 = await 2
console.log(f1.toString())
console.log(f2.toString())
}
Copy the code
const genFunction = function* () {
const f1 = yield 1
const f2 = yield 2
console.log(f1.toString())
console.log(f2.toString())
}
Copy the code
More practical type
co
Module convention,yield
Command can only be followed byThunk functionorPromise objectAnd theasync
Function of theawait
After the command, it can bePromise objectandA value of the original type(The numerical,stringandBoolean value, but it will automatically change toImmediate Resolved Promise object).
Copy the code
The return value is Promise
async
The return value of the function isPromise objectThan theGenerator
The return value of the function isIterator
Objects are much more convenient. You can usethen
Method specifies what to do next.
function getStockSymbol(name) {
const symbolName = Symbol(name)
return symbolName
}
function getStockUser(symbol) {
return symbol
}
async function getUserByName(name) {
const symbol = await getStockSymbol(name);
const stockUser = await getStockUser(symbol);
console.log('stockUser', stockUser)
return stockUser;
}
getUserByName('JackDan').then(function (result) {
console.log(result)
})
Copy the code
- And going further,
async
Functions can be thought of as multiple asynchronous operations wrapped into onePromise objectAnd theawait
The command is the insidethen
Syntax sugar for commands.
function timeout(ms) {
return new Promise((resolve) = > {
setTimeout(resolve, ms);
});
}
async function asyncPrint(value, ms) {
await timeout(ms)
console.log(value)
}
asyncPrint('hello world'.5000);
// Output hello world every 5 seconds
Copy the code
- Due to the
async
The function returns zeroPromise
Object that can be used asawait
Command parameters.
async function timeout(ms) {
await new Promise((resolve) = > {
setTimeout(resolve, ms);
});
}
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value);
}
asyncPrint('hello world'.3000);
// Output hello world every 3 seconds
Copy the code
The implementation principle of Async
- The implementation principle of async function is that the async function will
Generator
Functions andautoactuator, wrapped in a function.
async function asyncFunction() {
// ...
}
/ / is equivalent to
function asyncFunction(args) {
return spawn(function* () {
// ...})}function spawn(genFunction) {
// Returns a Promise object. Async also returns a Promise object
return new Promise(function(resolve, reject) {
const _gen = genFunction();
function step(nextFunction) {
let _next;
try {
_next = nextFunction();
} catch(e) {
return reject(e);
}
if(_next.done) {
return resolve(_next.value);
}
Promise.resolve(_next.value).then(function(v) {
step(function() { return _gen.next(v); });
}, function(e) {
step(function() { return _gen.throw(e); });
})
}
step(function() { return _gen.next(undefined); }); })}Copy the code
For a sample
var resolveAfter2Seconds = function () {
console.log("starting slow promise");
return new Promise((resolve) = > {
setTimeout(function() {
resolve('slow');
console.log("slow promise is done");
}, 20000);
});
};
var resolveAfter1Seconds = function () {
console.log("starting fast promise");
return new Promise((resolve) = > {
setTimeout(function() {
resolve('fast');
console.log("fast promise is done");
}, 1000);
});
};
var parallel = async function() {
console.log('==PARALLEL with await Promise.all==');
await Promise.all([
(async() = >console.log(await resolveAfter2Seconds()))(),
(async() = >console.log(await resolveAfter1Seconds()))()
]);
}
setTimeout(parallel, 10000);
Copy the code
var resolveAfter2Seconds = function () {
console.log("starting slow promise");
return new Promise((resolve) = > {
resolve('slow');
console.log("slow promise is done")},2000);
}
var resolveAfter1Seconds = function () {
console.log("starting fast promise");
return new Promise((resolve) = > {
resolve('fast');
console.log("fast promise is done");
}, 1000);
}
var sequentialStart = async function() {
console.log('==SEQUENTIAL START==');
// 1. Execution gets here almost instantly
const slow = await resolveAfter2Seconds();
console.log(slow); // 2. this runs 2 seconds after 1.
const fast = await resolveAfter1Second();
console.log(fast); // 3. this runs 3 seconds after 1.
}
Copy the code
var resolveAfter2Seconds = function () {
console.log("starting slow promise");
return new Promise((resolve) = > {
resolve('slow');
console.log("slow promise is done")},2000);
}
var resolveAfter1Seconds = function () {
console.log("starting fast promise");
return new Promise((resolve) = > {
resolve('fast');
console.log("fast promise is done");
}, 1000);
}
var concurrentStart = async function() {
console.log('==CONCURRENT START with await==');
const slow = resolveAfter2Seconds(); // starts timer immediately
const fast = resolveAfter1Second(); // starts timer immediately
// 1. Execution gets here almost instantly
console.log(await slow); // 2. this runs 2 seconds after 1.
console.log(await fast); // 3. this runs 2 seconds after 1., immediately after 2., since fast is already resolved
}
Copy the code
JackDan Thinking
Developer.mozilla.org/zh-CN/docs/…
Developer.mozilla.org/zh-CN/docs/…