Node教程——讲一下我们的异步API还有Promise对象

五、异步API

导学:

通过返回值拿结果
path.join()
通过函数拿结果,fs.redFile~

在node中有两种api

同步的api还有异步的api

  1. 同步
    所谓的同步就是一步一步的走

  2. 异步
    当前的api不会堵塞后续的代码的执行

  3. 对比

  • 第一个区别
    二者最大的区别:同步的api可以从返回值拿结果,异步的就不行
    你只需要知道,异步的api是通过回调函数拿结果

  • 第二个区别
    同步的api会堵塞,我们的异步api不会堵塞

注意:同步还有异步还有任务队列都是非常基础的东西,这里做过多的解释,有需要可以去百度查询对应的东西

(一)、Node中的异步api

不能通过返回值拿结果

这里举例说明
读取文件的操作是异步的

fs.readFile(‘./demo.txt‘,( err,result )=>{

})

事件监听也是异步的

let server = http.creareServe();

server.on(‘request‘, ( req.res )=>{})
// ....当然了我们还有很多的异步api,这里不一一列举
  • 提出问题

如果异步后面的api依赖前面的api的执行结果怎么办??

解决1:后续的操作写在回调里面,不推荐,因为太复杂,回调层次太多,不好维护,会变 ‘回调地狱’,比如下面的代码

//这里的代码,旨在依次的读取 A B C三个文件

const fs = require(‘fs‘);

//通过回调函数依次的执行,这个是不可维护的代码,回调回调,再回调=哭了,回调地狱
fs.readFile(‘./1.txt‘, ‘utf8‘, (err, result1) => {
    console.log(result1)
    fs.readFile(‘./2.txt‘, ‘utf8‘, (err, result2) => {
        console.log(result2)
        fs.readFile(‘./3.txt‘, ‘utf8‘, (err, result3) => {
            console.log(result3)
        })
    })
});

解决2:Promise对象 ,解决异步回调的问题,以下来看看使用的步骤

简单的使用


    const fs = require(‘fs‘);

// 说明“1. 异步api的结果与异步相分离

// 说明“2. resolve reject都是两个函数,第一一个把正确的结果丢到外面出去。第二个就是把失败的结果丢到外面去

//1.实例化对象
let promise = new Promise(
    //2.实例化的时候把匿名函数弄进去
    (resolve, reject) => {
    fs.readFile(‘./100.txt‘, ‘utf8‘, (err, result) => {
        //业务逻辑,如果那么
        if (err != null) {
            reject(err);
        } else {
            resolve(result);
        }
    });
}

);
// 说明“3. 通过the方法,把 resolve reject接过来
    
//3.在外面接受结果
promise.then((result) => {
        console.log(result);
    })
    .catch((err) => {
        console.log(err);
    })

看看我们怎么解决之前的回调地狱问题


//1.实例化对象,注意我们要保证依次的执行就需要放在函数里面

// let p1 = new Promise((resolve, reject) => {
//     fs.readFile(‘./1.txt‘, (erro, result) => {
//         // 读取之后调用这个参数函数,把成功的结果丢到外面去
//         resolve(result)
//     })
// })
// let p3 = new Promise((resolve, reject) => {
//     fs.readFile(‘./2.txt‘, (erro, result) => {
//         resolve(result)
//     })
// })
// let p1 = 3 = new Promise((resolve, reject) => {
//     fs.readFile(‘./3.txt‘, (erro, result) => {
//         resolve(result)
//     })
// })


// function p1() {
//     let p1 = new Promise((resolve, reject) => {
//         fs.readFile(‘./1.txt‘, (erro, result) => {
//             // 读取之后调用这个参数函数,把成功的结果丢到外面去
//             resolve(result)
//         })
//     })

// }

// function p2() {
//     let p2 = new Promise((resolve, reject) => {
//         fs.readFile(‘./2.txt‘, (erro, result) => {
//             // 读取之后调用这个参数函数,把成功的结果丢到外面去
//             resolve(result)
//         })
//     })

// }

// function p3() {
//     let p3 = new Promise((resolve, reject) => {
//         fs.readFile(‘./3.txt‘, (erro, result) => {
//             // 读取之后调用这个参数函数,把成功的结果丢到外面去
//             resolve(result)
//         })
//     })
// } 默认函数返回undefined.then???

// 细节,只有我们的promise对象才能.then啥啥啥的。我的意思是只有 promise对象才行执行它应该有的操作,所以你需要在函数里面把promise返回出来

function p1() {
    // 为什么要rreturn是因为,我们在后学的p1().then()中要有返回值
    return new Promise((resolve, reject) => {
        fs.readFile(‘./1.txt‘, ‘utf8‘, (err, result) => {
            resolve(result)
        })
    });
}

function p2() {
    return new Promise((resolve, reject) => {
        fs.readFile(‘./2.txt‘, ‘utf8‘, (err, result) => {
            resolve(result)
        })
    });
}

function p3() {
    return new Promise((resolve, reject) => {
        fs.readFile(‘./3.txt‘, ‘utf8‘, (err, result) => {
            resolve(result)
        })
    });
}


// 2. 在外面接收,处理

// 这里的r1 r1是接受的一个形参数,相当与r1 = 异步的结果,这样子的代码是不纯在嵌套的
p1().then((r1) => {
        console.log(r1);
        //注意:我们是在p1再把retun出去,下一个the就是这个retrub的结果,而这个retun的结果就保存到r2中了
        return p2(); //这是语法,不讲了,获取的就是一个promise对象
    })
    //链式编程,直接点击then
    .then((r2) => {
        console.log(r2);
        return p3();
    })
    .then((r3) => {
        console.log(r3)
    })

不过,现在又有问题了,我还是觉得这个代码太复杂的,我们有没有什么方式,把异步的写成同步的样子。我的意思是说。我想让我的异步代码看起来像同步代码一样,因为我看起来舒服。看起来简单明了。

解决:异步函数,async,在普通的函数前加一个这个关键字 ,我们的函数就变成异步的了

语法代码演示:

// 1.在普通函数定义的前面加上async关键字 普通函数就变成了异步函数
// 2.异步函数默认的返回值是promise对象不是undecided!!!
// 3.在异步函数内部使用throw关键字进行错误的抛出
// 
// await关键字
// 1.它只能出现在异步函数中
// 2.await promise 它可以暂停异步函数的执行 等待promise对象返回结果后再向下执行函数

// async function fn () {
// 	throw ‘发生了一些错误‘;
// 	return 123;
// }

// // console.log(fn ())
// fn ().then(function (data) {
// //then是为了回去异步函数的结果
// 	console.log(data);
// }).catch(function (err){
// 	console.log(err);
// })

async function p1() {
    return ‘p1‘;
}

async function p2() {
    return ‘p2‘;
}

async function p3() {
    return ‘p3‘;
}

//通过异步函数再去一个一个的跑出来!
async function run() {
    //这里是一个 await
    let r1 = await p1() //只要没有拿到P1回送的promise对象,我们就不向下执行,这个就是await的作用
    let r2 = await p2()
    let r3 = await p3()
    console.log(r1)
    console.log(r2)
    console.log(r3)
}

run();

总结:

  1. async关键词
  • 普通函数定义前加async关键字 普通函数变成异步函数
  • 异步函数默认返回promise对象
  • 在异步函数内部使用return关键字进行结果返回 结果会被包裹的promise对象中 return关键字代替了resolve方法
  • 在异步函数内部使用throw关键字抛出程序异常
  • 调用异步函数再链式调用then方法获取异步函数执行结果
  • 调用异步函数再链式调用catch方法获取异步函数执行的错误信息
  1. await关键字
  • await关键字只能出现在异步函数中
  • await promise await后面只能写promise对象 写其他类型的API是不不可以的
  • await关键字可是暂停异步函数向下执行 直到promise返回结果

解决之前的读取文件的

const fs = require(‘fs‘);
// 1. 改造现有异步函数api 让其返回promise对象 从而支持异步函数语法,异步语法去包装原来的异步api返回的结果
const promisify = require(‘util‘).promisify; //用一个变量去获得这个 promisify 方法
// 2. 调用promisify方法改造现有异步API 让其返回promise对象
//我们看一下到底拿到了什么鬼东西
console.log(promisify);
//{ [Function: promisify] custom: Symbol(util.promisify.custom) }
const readFile = promisify(fs.readFile); //这个返回值是一个promise对象
//我们看一下到底拿到了什么鬼东西
// [Function: readFile],这个就是我们的代码
console.log(readFile);

//3.于是乎我们的阿的
async function run() {
    let r1 = await readFile(‘./1.txt‘, ‘utf8‘)
    let r2 = await readFile(‘./2.txt‘, ‘utf8‘)
    let r3 = await readFile(‘./3.txt‘, ‘utf8‘)
    console.log(r1)
    console.log(r2)
    console.log(r3)
}
run();

(二)、全局对象global

不知道你有没有注意到,在学习web API的时候我们说过 我们的 console.log()是window下面,但是我们的node运行中也可以使用,那么有问题来了,我们的这里的console.log()是谁的?答案是:global的

(三)、网站服务器

一个完整的网站就是一个,包含两个部分:浏览器还有一个与之对应的服务器

接下里,我们来学习轻量级且强大的MongoDB数据库软件,还有我们的这个Node服务器开发框架Express

Node教程——讲一下我们的异步API还有Promise对象

上一篇:百度地图API-根据地址解析坐标,根据坐标解析地址


下一篇:Node.js安装及环境配置之Windows篇