Why is JS asynchronous?
javascript
is a single-threaded language, that is, only one task can be completed at a time. If there are multiple tasks to be executed, they must be queued to complete the task, and the previous task can be executed before the next task can be executed.
Then if the previous task is not over, the next task will never be executed, or the previous task has been executed for a long time, there is no necessary connection between the two tasks before and after, and time is wasted waiting.
So it needs to be asynchronous.
Asynchronous operations commonly used in development
- Network request
IO
Operationreadfile readDir
- Timing function
setTimeout setInterval
etc. - In Node.js there is also
process.nextTick() setImmediate()
Traditional asynchronous solutions:
- Event subscription/publishing mechanism
- Callback
Publish/subscribe mechanism
Simple example
// 订阅
emitter.on('eventName', function(message){
console.log(message)
})
// 发布
emitter.emit('eventName', 'I am a message')
We can see its application in Node.js
var options = {
hostname: '127.0.0.1',
port: 10086,
path: '/pay/pay_callback?' + content,
method: 'GET'
};
var req = http.request(options, function (res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
res.on('end', function() {
})
});
req.on('error', function (e) {
console.log('problem with request: ' + e.message);
});
req.end();
The above is a process of requesting an interface. As a developer, we only need to pay attention to error、data、end
. After subscribing to these events, it will automatically trigger the corresponding event when executing the internal process.
The traditional way of callback function will cause callback hell, similar to this
fs.readFile('some1.json', (err, data) => {
fs.readFile('some2.json', (err, data) => {
fs.readFile('some3.json', (err, data) => {
fs.readFile('some4.json', (err, data) => {
})
})
})
})
Promise circumvents this point and uses the form of chain call, which is more readable
readFilePromise('some1.json').then(data => {
return readFilePromise('some2.json')
}).then(data => {
return readFilePromise('some3.json')
}).then(data => {
return readFilePromise('some4.json')
})
Asynchronous to synchronous
This is a scenario that we often encounter when developing, asynchronous code is executed synchronously.
Write two simulated asynchronous functions
var f1 = function() {
return new Promise(resolve => {
setTimeout(() => {
console.log('f1 is run');
resolve('f1 done')
}, 3000)
})
}
var f2 = function() {
return new Promise(resolve => {
setTimeout(() => {
console.log('f2 is run');
resolve('f2 done')
}, 2000)
})
}
Promise
f1().then(res => { return f2() }).then(res => { }) // 输出 3s后输出:f1 is run 再过2s后输出:f2 is run
If there are many asynchronous functions, there will be many
then
f1().then(res => { return f2() }).then(res => { return f3() }).then...
Can be written more concisely
var arr = [f1, f2] // 待执行promise数组 var p = Promise.resolve() for(let pro of arr) { p = p.then(res => pro(res)) }
reduce
Actually the same as 1var arr = [f1, f2] arr.reduce((p,c) => { return p.then((res) => c(res)) }, Promise.resolve())
async await
var arr = [f1, f2] async function doFunc() { for(let p of arr) { await p() } }
Generator
function * gen() { yield f1() yield f2() } let g = gen() g.next() g.next()
The above methods can achieve the result of secondary execution.
1.2.3.4 are all executed and then output. What if it is executed concurrently and then output in order? It is a bit similar to Promise.all
, in fact, it is concurrent execution, and then the execution result is stored first, and then output in order. This is more efficient for concurrent execution of two unrelated asynchronous functions.
async function testFunc() {
var arr = [f1, f2]
// 并发执行
var promiseArr = arr.map((fn) => fn())
for(let result of promiseArr) {
// 同步返回结果
console.log('result', await result);
}
}
// 输出
f2 is run
f1 is run
result f1 done
result f2 done
Promise
For Promise, we have to memorize it according to the main points
- Long chain call
Promise
notresolve
orreject
, it will always be in the statepending
- If it is in
pending
, it is impossible to know whether it is just beginning or about to end
- If it is in
- Cannot cancel
Promise
once it is created, it will be executed immediately, and cannot be canceled halfway
- Cannot cancel
- If the callback function is not set,
Promise
will not be reflected to the outside (so it is generally recommended that thepromise
object be followed by thecatch
method)
- If the callback function is not set,
- Once the state changes, it will remain in that state forever and will not change anymore
- If it is a chain call
promise
object is consistent with the new object
- If it is a chain call
reject
is equivalent to throwing an error
catch
method returns thepromise
object (you can continue to followthen
)
Promise
object of 0613c24c22d2e9 immediately isresolve()
at the end of the current round of "event loop"(event loop)
, not at the beginning of the next round of "event loop"
For point 2, give an example:
function pend () {
return new Promise(resolve => {
// 没有resolve
console.log('aaaa');
})
}
pend().then(() => {
console.log('bbb');
})
// 输出
aaaa
Promise {<pending>}
bbb
will never be printed
For point 9, give an example:
setTimeout(() => {
console.log('three');
},0)
Promise.resolve().then(() => {
console.log('two');
})
console.log('one');
// 输出
one
two
three
one
is output immediatelytwo
is executed at the end of the "this round" event loop and then outputthree
is executed at the beginning of the next round of event loop and then output
The writing is a bit general. Follow-up will add more questions. Welcome to discuss together.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。