zoukankan      html  css  js  c++  java
  • Node教程——异步API

    五、异步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

  • 相关阅读:
    OnEraseBkgnd、OnPaint与画面重绘
    .编译ADO类DLL时报错的解决方案
    VC列表框样式
    Codeforces 131D. Subway 寻找环树的最短路径
    Codeforces 103B. Cthulhu 寻找奈亚子
    Codeforces 246D. Colorful Graph
    Codeforces 278C. Learning Languages 图的遍历
    Codeforces 217A. Ice Skating 搜索
    Codeforces 107A. Dorm Water Supply 搜图
    Codeforces 263 D. Cycle in Graph 环
  • 原文地址:https://www.cnblogs.com/BM-laoli/p/12661494.html
Copyright © 2011-2022 走看看