• 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

  • 相关阅读:
    RootMotionComputer 根运动计算机
    tar压缩解压缩命令详解
    解决有关flask-socketio中服务端和客户端回调函数callback参数的问题
    flask-sqlalchemy中Datetime的创建时间、修改时间,default,server_default,onupdate
    sqlalchemy和flask-sqlalchemy的几种分页方法
    Flask路由报错:raise FormDataRoutingRedirect(request)
    解决Python自带的json不能序列化data,datetime类型数据问题
    Python中将字典转换为有序列表、无序列表的方法
    flask-sqlalchemy 一对一,一对多,多对多操作
    python2 UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 7: ordinal not in range(128)
  • 原文地址:https://www.cnblogs.com/BM-laoli/p/12658838.html
Copyright © 2020-2023  润新知