js 异步编程

127 阅读2分钟

文件准备

image.png

a.txt

aaa

b.txt

bbb

c.txt

ccc

一、依次读取文件

01-依次读取文件

const fs = require('fs')
// 依次读取文件(会发现读取结果很不稳定)
fs.readFile('./txt/a.txt', 'utf8', (err, data) => {
    if (err) return console.log(err.message);
    console.log(data);
})
fs.readFile('./txt/b.txt', 'utf8', (err, data) => {
    if (err) return console.log(err.message);
    console.log(data);
})
fs.readFile('./txt/c.txt', 'utf8', (err, data) => {
    if (err) return console.log(err.message);
    console.log(data);
})

多 node 几下,读取结果很不稳定,并不如你所料吧

image.png

二、体验回调地狱

02-体验回调地狱

const fs = require('fs')
fs.readFile('./txt/a.txt', 'utf8', (err, data) => {
    if (err) return console.log(err.message);
    console.log(data);
    fs.readFile('./txt/b.txt', 'utf8', (err, data) => {
        if (err) return console.log(err.message);
        console.log(data);
        fs.readFile('./txt/c.txt', 'utf8', (err, data) => {
            if (err) return console.log(err.message);
            console.log(data);
        })
    })
})

虽然解决了问题,但是造成了新的问题——回调地狱

image.png

三、Promise 解决回调地狱

03-Promise解决回调地狱

const fs = require('fs')
// 创建promise对象
let p1 = new Promise((resolve, reject) => {
    // 读取文件
    fs.readFile('./txt/a.txt', 'utf8', (err, data) => {
        //不考虑失败的情况
        resolve(data)
    })
})

let p2 = new Promise((resolve, reject) => {
    fs.readFile('./txt/b.txt', 'utf8', (err, data) => {
        resolve(data)
    })
})

let p3 = new Promise((resolve, reject) => {
    fs.readFile('./txt/c.txt', 'utf8', (err, data) => {
        resolve(data)
    })
})

// 输出内容  回调地狱
/* p1.then(res=>{
    console.log(res);
    p2.then(res=>{
        console.log(res);
        p3.then(res=>{
            console.log(res);
        })
    })
    
}) */

// 怎么办链式编程,返回值
// then() 的返回值,默认是 then() 参数的返回值,如果没有返回值,默认返回一个空白的promise对象
p1.then(res => {
    console.log(res);
    return p2
}).then(res => {
    console.log(res);
    return p3
}).then(res => {
    console.log(res);
})

image.png

以上代码优化——封装 Promise 解决回调地狱

const fs = require('fs')
// ◆封装一个函数,调用这个函数,返回一个promise对象
// 法1
// function getPromise(url){
//     // 创建promise对象
//     let p1=new Promise((resolve,reject)=>{
//         // 读取文件
//         fs.readFile(url,'utf8',(err,data)=>{
//             resolve(data)//不考虑失败的情况
//         })
//     })
//     return p1
// }

// 法2
 function getPromise(url){
    // 创建promise对象
   return  new Promise((resolve,reject)=>{
        // 读取文件
        fs.readFile(url,'utf8',(err,data)=>{
            resolve(data)//不考虑失败的情况
        })
    })
} 

// ◆调用封装的 Promise 函数
getPromise('./txt/a.txt').then(res=>{
    console.log(res);
    return getPromise('./txt/b.txt')
}).then(res=>{
    console.log(res);
    return getPromise('./txt/c.txt')
}).then(res=>{
    console.log(res);
})

四、thenFs 解决回调地狱

04-thenFs解决回调地狱

// 查看两个模块中, readFile() 的返回值
const fs = require('fs')
let a = fs.readFile('./txt/a.txt', 'utf8', () => { })
console.log(a);//undefined

// thenFs 使用 promise 对象处理函数,所以不需要函数处理结果!
const thenFs = require('then-fs')
let b = thenFs.readFile('./txt/a.txt', 'utf8')
console.log(b);// Promise

// ◆ thenFs 解决回调地狱
thenFs.readFile('./txt/c.txt', 'utf8').then(res => {
    console.log(res);
    return thenFs.readFile('./txt/b.txt', 'utf8')
        .then(res => {
            console.log(res);
            return thenFs.readFile('./txt/a.txt', 'utf8')
        }).then(res => {
            console.log(res);
        })
})

image.png

五、async await 解决回调地狱

05-async await解决回调地狱

// 导入 then-fs
const thenFs = require('then-fs')
// await 一定要出现在异步函数中
async function fn() {
    let res1 = await thenFs.readFile('./txt/c.txt', 'utf8')
    console.log(res1);
    let res2 = await thenFs.readFile('./txt/b.txt', 'utf8')
    console.log(res2);
    let res3 = await thenFs.readFile('./txt/a.txt', 'utf8')
    console.log(res3);
}

// 调用函数
fn()

image.png