• 技术文章 >web前端 >js教程

    深入浅析Node.js中的异步

    青灯夜游青灯夜游2021-06-08 18:54:48转载66
    本篇文章给大家详细介绍一下Node.js中的异步。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

    关于 Node.js 异步,绕不开两点:非阻塞 I/O事件循环。也正是因为这两点,Node.js 才能被称为高性能并运用到线上环境中,那么下面来了解一下 Node.js 的异步机制和使用方式吧!【推荐学习:《nodejs 教程》】

    Node.js 的非阻塞 I/O

    以点菜吃饭为例子:去饭堂点菜吃饭需要排队等待,在这个过程中,阿姨每次只能接待一个人,“点菜-阿姨抖勺装菜-把饭菜给到你”这个过程中阿姨并不能接收其他人的点菜,这个就是阻塞 I/O;而去餐馆点菜吃饭,去到餐馆就可以跟服务员你要吃番茄炒蛋,服务员记下来之后交给后厨,这时候来了另一桌人就把服务员招呼过去说想吃小龙虾,也就是说,在把菜给你上上来之前服务员接收了其他人的点菜,那这个就是非阻塞型 I/O。

    理解非阻塞 I/O 的要点在于

    那在点菜吃饭这个例子中,一个进行 Input/Output 的系统就是点餐-后厨(阿姨)处理-上菜这样一个能让你吃上饭的系统;点餐就是 Input,上菜就是 Output,在这个例子中判断两者是非阻塞型还是阻塞型的关键就在于在点菜上菜这个过程中能不能接受其它的点菜上菜。就好比你点了个佛跳墙,等上菜可能就要好久了,然后来的人都是点一些简单的菜品,一分钟炒一份炒粉的那种,可能就是来来回回几波人之后都还没能给你上菜。

    而 Node.js 它是用来操纵计算机的,一些如读取文件之类的操作是非常耗时的,要是不能进行其它的 I/O,那么处理效率就很会很低了,这也是 Node.js 是非阻塞型 I/O 的一个原因。

    Node.js 的事件循环

    Node.js 启动的时候会初始化由 libuv 提供的事件循环,每次的事件循环都包含6个阶段,这6个阶段会在每一次的事件循环当中按照下图当中的顺序反复执行,如下图:

    1.png

    每个阶段都有一个先入先出的(FIFO)的用于执行回调的队列,事件循环运行到每个阶段,都会从对应的回调队列中取出回调函数去执行,直到队列当中的内容耗尽,或者执行的回调数量达到了最大

    然后事件循环就会进入下一个阶段,然后又从下一个阶段对应的队列中取出回调函数执行,这样反复直到事件循环的最后一个阶段。而事件循环也会一个一个按照循环执行,直到进程结束。

    事件循环当中的6个宏队列和微队列的关系如下:微队列(microtask)在事件循环的各个阶段之间执行,或者说在事件循环的各个阶段对应的宏队列(macrotask)之间执行。

    2.png

    这里有一个特别容易混淆的版本改变:

    Node.js 异步编程 - callback

    // 第一个参数是错误捕获
    interview(function (err, res) {
      if (err) {
        console.log('cry')
        return;
      }
      console.log('smile')
    })
    function interview(callback) {
      setTimeout(() => {
        if (Math.random() > 0.2) {
          callback(null, 'success')
        } else {
          callback(new Error('fail'))
        }
      }, 500)
    }

    异步流程控制:回调地狱、异步并发等问题

    Node.js 异步编程 – Promise

    链式调用:.then.catch

    // promise的状态转换以及通过then获取内容
    const promise = new Promise((resolve, reject) => {
      setTimeout(function () {
        resolve(3);
        // reject(new Error(4))
      }, 500)
    })
    
    promise.then(function (result) {
      console.log(result)
    }).catch(function (err) {
      console.log(err)
    })
    
    setTimeout(() => {
      console.log(promise)
    }, 800)

    执行 thencatch 会返回一个新 Promise,该 Promise 最终状态根据 thencatch 的回调函数的执行结果决定

    Node.js 异步编程 – async/await

    (async function () {
      await findJob()
      console.log('trip')
    })()
    
    async function findJob() {
      try {
        // 进行三轮面试
        await interview(1);
        await interview(2);
        await interview(3);
        console.log('smile')
      } catch (e) {
        console.log('cry at ' + e.round)
      }
    }
    
    // 进行第round轮面试
    function interview(round) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (Math.random() < 0.2) {
            const error = new Error('failed');
            error.round = round;
            reject(error);
          } else {
            resolve('success');
          }
        }, 500)
      })
    }

    这是一个穿越事件循环存在的 function

    总结

    更多编程相关知识,请访问:编程视频!!

    以上就是深入浅析Node.js中的异步的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    专题推荐:Node.js 异步
    上一篇:javascript print方法怎么用 下一篇:Angular中关于单元测试的面试题,你能回答上来吗?
    第16期线上培训班

    相关文章推荐

    • 如何使用Nodejs连接Mysql,实现基本的增删改查操作• Nodejs如何实现简单的GET请求• 深入了解调试nodejs程序的方法• 浅谈浏览器中本地运行Node.js的方法• 详解使用Docker给nodejs程序打包的方法• 聊聊Nodejs中的模块化和事件循环

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网