zoukankan      html  css  js  c++  java
  • 学习笔记—Generator和async/await

    日常的学习笔记,包括 ES6、Promise、Node.js、Webpack、http 原理、Vue全家桶,后续可能还会继续更新 Typescript、Vue3 和 常见的面试题 等等。

    同步阻塞与异步非阻塞

    在了解异步的发展之前,我们要先清楚一个概念。那就是 同步异步与阻塞

    在执行代码的过程中,我们可能调用了某个方法。在调用方法时,如果方法没有执行完毕的话,后续的其他代码就无法向下执行,那么我当前的状态就是 阻塞态。 反之,便是 非阻塞态

    通过上述描述我们清楚了一个道理,那就是 阻塞与非阻塞指的是调用方的状态

    而针对于被调用方 ,延迟发送结果我们就可以称为 异步 ,而实时发送结果我们就可以称为 同步同步与异步指的是被调用方的状态

    所以在实际概念中,同步非阻塞是可能存在的,但异步阻塞是一定不存在的

    Promise 最早是为了解决异步的回调地狱问题,但是却并没有从根本上解决这个问题,所以我们可以考虑使用 Generator

    Generator

    参考文献 Generator函数的含义与用法

    Generator 是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。

    基础语法

    在普通函数中,我们可以利用 return 将函数的控制权交还给被调用的代码。

    function read(n) {
        return n + n;
    }
    
    let it = read(1); // 调用foo函数
    

    函数在执行过程中,如果没有遇到return语句(函数末尾如果没有return,就是隐含的return undefined;),控制权无法交回被调用的代码。

    而我们的 Generator 的语法与函数相似,却又有一些不同。

    Generatorfunction*定义(注意多出的*号),并且,除了return语句,还可以用yield返回多次。

    function* read() { // 生成器,他的执行结果叫做迭代器
        console.log(1);
        yield 1;
        console.log(2);
        yield 2;
        console.log(3);
        yield 3;
    }
    let it = read();  // 默认没有执行
    // next方法触发回调
    it.next();
    

    定义的函数我们可以叫他 生成器,其执行结果我们可以叫做 迭代器

    实现原理

    关于 Generator 的实现原理,我们可以从 babel官网 上进行查看。

    image.png

    通过打印,我们可以很清楚的发现一件事情。 那就是 Genetator 实现原理的核心方法就是 switch...case

    我们每次在执行代码时,会在遇到 yield 时,将控制权交还给被调用的代码。等待下一次 .next() 方法,再执行后续的代码。

    实际案例

    假设我们现在有一个文件 a.txt,里面有 b.txt的路径(如 ./b.txt), 再将此内容作为参数,继续请求路径为 b.txt 的文件,得到结果 b。

    实现上述需求,利用 Generator 可以解决我们在请求过程中的回调地狱问题

    const util = require('util');
    const fs = require('fs');
    let readFile = util.promisify(fs.readFile);
    // 解决了回调地狱
    function* read() {
        let data = yield readFile('./a.txt', 'utf-8')
        data = yield readFile(data, 'utf-8')
        return data
    }
    // 依旧存在回调地狱的问题
    let it = read()
    let { value } = it.next()
    value.then(data => {
        let { value } = it.next(data)
        value.then(data => {
            let { value } = it.next(data)
            console.log(value) // b
        })
    })
    

    我们可以发现,发送请求时,我们利用 Generator 对异步请求进行了封装,使代码看起来更整洁了。

    但是在调用的时候,依旧存在回调地狱的问题。

    调用的回调地狱问题,我们可以使用 tj/co 库来进行处理。

    这个库的实现原理,就是实现 async/await 的核心思路。

    co插件

    使用co库,可以直接将 Generator 函数的最终结果返回,而且会使代码看起来更简洁优雅。

    npm install co 先安装插件库。

    const co = require('co');
    
    co(read()).then(data => {
        console.log(data) // b
    })
    

    直接会将结果返回。

    实现原理

    function co(it) {
        return new Promise((resolve, reject) => {
            // 异步迭代,我们只能使用递归的方式
            function next(data) {
                let {
                    value,
                    done
                } = it.next(data);
                // 如果执行完毕,则将最终结果返回
                if (done) {
                    resolve(value);
                } else {
                    Promise.resolve(value).then(next, reject)
                }
            }
            next();
        })
    }
    

    async/await

    还是参考上面那个例子。

    const util = require('util');
    const fs = require('fs');
    const co = require('co');
    let readFile = util.promisify(fs.readFile);
    
    function* read() {
        let data = yield readFile('./a.txt', 'utf-8')
        data = yield readFile(data, 'utf-8')
        return data
    }
    
    co(read()).then(data => {
        console.log(data) // b
    })
    

    async/await 的实现思路就是 Generator,将 Generator 中的 function * 替换成 async function ,把 yield 替换成 await

    async function read() {
        let data = await readFile('./a.txt', 'utf-8')
        data = await readFile(data, 'utf-8')
        return data
    }
    
    read().then(data => {
        console.log(data) // b
    })
    

    这样我们就可以直接输出最终结果。

    可以说 async/await 是目前解决回调地狱问题的最优方案。


    本篇文章由莫小尚创作,文章中如有任何问题和纰漏,欢迎您的指正与交流。
    您也可以关注我的 个人站点博客园掘金,我会在文章产出后同步上传到这些平台上。
    最后感谢您的支持!

  • 相关阅读:
    MySQL之自增长
    MySQL字符集和校对规则
    关于MySQL安装目录bin下工具的详解
    Linux下载安装配置FTP
    Linux和Windows平台安装MySQL的两种方式
    kali安装linux-header
    Mysql之事务
    Linux之ps命令
    Linux之dd命令
    python爬虫之xpath的基本使用
  • 原文地址:https://www.cnblogs.com/moxiaoshang/p/15495576.html
Copyright © 2011-2022 走看看