从一个简单的案例开始
依次读取a.txt 、 b.txt 、 c.txt 的内容
a.txt
this is a
b.txt
this is b
c.txt
this is c
如果按照一般的方法,a b c中的文件不会依次读出,会打乱顺序的
nodejs 特点是单线程、异步,如果代码逻辑涉及到多个回调,就会出现非常可怕的代码,不利于后期的维护。
对于异步的理解
当一段代码中同时有同步代码和异步代码时,他会先执行同步的代码,将异步的代码放到一边,最后在执行,而这样的话就会产生很大的问题,不能够及时获取到信息
异步编程的解决方案
有一种最古老的办法就是回调
const fs = require('fs')
const path = require('path')
let a_path = path.join(__dirname, 'file', 'a.txt')
let b_path = path.join(__dirname, 'file', 'b.txt')
let c_path = path.join(__dirname, 'file', 'c.txt')
fs.readFile(a_path, 'utf8', (err, data) => {
if (err) throw err
console.log(data)
fs.readFile(b_path, 'utf8', (err, data) => {
if (err) throw err
console.log(data)
fs.readFile(c_path, 'utf8', (err, data) => {
if (err) throw err
console.log(data)
})
})
})
这样的话,容易产生回调地狱的问题,一旦代码多了就容易出问题
1.promise
Promise对象具备then方法,接受完成态、失败态的调用,只接受function对象,其余对象将被忽略。then方法继续返回Promise对象,以实现链式调用。
const fs = require('fs')
const path = require('path')
let a_path = path.join(__dirname, 'file', 'a.txt')
let b_path = path.join(__dirname, 'file', 'b.txt')
let c_path = path.join(__dirname, 'file', 'c.txt')
function readFile(path){
return new Promise((resolve,reject)=>{
fs.readFile(path,'utf8',(err,data)=>{
resolve(data)
})
})
}
let p1 =readFile(a_path)
p1.then(data=>{
console.log(data)
return readFile(b_path)
}).then(data=>{
console.log(data)
return readFile(c_path)
}).then(data=>{
console.log(data)
})
调用then方法时才会立即执行 resolve(data) ,这样的链式就减少了代码的嵌套
2.async和await
const fs = require('fs')
function readFile(path) {
return new Promise((resolve, reject) => {
fs.readFile(path, 'utf8', (err, data) => {
resolve(data)
})
})
}
async function exec() {
await readFile('./file/a.txt').then(result => console.log(result))
await readFile('./file/b.txt').then(result => console.log(result))
await readFile('./file/c.txt').then(result => console.log(result))
}
exec()
- await后面接一个会return new promise的函数并执行它
- await只能放在async函数里
- 为什么要用await
为了使我们的异步代码,看起来更像同步的代码
await等到以后做了什么事情?
如果不是 promise , await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,把这个非promise的东西,作为 await表达式的结果。
如果它等到的是一个 promise 对象,await 也会暂停async后面的代码,先执行async里面的同步代码,等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果。