青训营node.js基础-异步编程四种解决方案(代码片段)

YK菌 YK菌     2022-12-12     766

关键词:

文章目录

有异步I/O,必有异步编程!今天来学习Node.js里的异步编程!

异步编程概述

曾经的单线程模型在同步I/O的影响下,由于I/O调用缓慢,在应用层面导致CPU与I/O无法重叠进行。为了照顾编程人员的阅读思维习惯,同步I/O盛行了很多年。

但是有很大的性能问题!

Node利用JavaScript及其内部异步库,将异步直接提升到业务层面。Node带来的最大特性莫过于基于事件驱动的非阻塞I/O模型。非阻塞I/O可以使CPU与I/O并不相互依赖等待,让资源得到更好的利用。

异步编程解决方案

目的:读取package.json 中main 字段对应的文件内容

Callback

使用回调函数进行异步I/O的操作

const fs = require("fs");

fs.readFile("./package.json",  encoding: "utf-8" , (err, data) => 
  if (err) throw err;
  const  main  = JSON.parse(data);
  fs.readFile(main,  encoding: "utf-8" , (err, data) => 
    if (err) throw err;
    console.log(data);
  );
);

问题:如何解决回调地狱?

Promise

Promise是一个具有四个状态的有限状态机,其中三个核心状态为Pending(挂起),Fulfilled(
完成)、Rejected(拒绝),以及还有一个未开始状态

详细内容可以看我之前的博文 Promise初探

使用Promise,实现读取 package.json 中 main 字段对应的文件内容

const  readFile  = require("fs/promises");

readFile("./package.json",  encoding: "utf-8" )
  .then((res) => 
    return JSON.parse(res);
  )
  .then((data) => 
    return readFile(data.main,  encoding: "utf-8" );
  )
  .then((res) => 
    console.log(res);
  );

对比之前用Callback的解决方案,可以看出没有嵌套的回调了,通过一系列的链式调用来处理异步操作。

Callback 转为 Promise

如何将 Callback 转为 Promise 形式?

可以使用Node自带的工具函数 util.promisify

可以自己实现一下:

function promisify(fn, receiver) 
  return (...args) => 
    return new Promise((resolve, reject) => 
      fn.apply(receiver, [
        ...args,
        (err, res) => 
          return err ? reject(err) : resolve(res);
        ,
      ]);
    );
  ;


const readFilePromise = promisify(fs.readFile, fs);

await

await 函数使用 try catch 捕获异常(注意并行处理)

const  readFile  = require("fs/promises");

const start = async () => 
  const  main  = JSON.parse(
    await readFile("./package.json",  encoding: "utf-8" )
  );
  const data = await readFile(main,  encoding: "utf-8" );
  console.log(data);
;
start();

await的语法写起来就像同步编程一样,这里的操作是串行操作,会一行一行的等待执行。

如果几个任务是可以并行的,这样写就不太好了。这是,我们可以使用Promise.all来操作并行的任务

这里也会有个小问题,我课后问老师了,这是老师的解答

【问】在异步那块,说到串行和并行,在并行处理那块我有一个疑问。如果并行的场景要求:不管其他任务执行成功还是失败,每个异步任务都要执行完,最后统一处理错误,那在用Promise.all来处理多个异步任务时候,遇到第一个任务执行错误的时候就会返回,如何操作才能让所有任务都执行完成,再统一处理错误呢

【答】Promise.all 处理多个请求,当所有请求都成功的时候,resolve 一个数组回来,里面是执行结果。如果有一个请求失败就立刻 reject 那个错误来,所以这个地方我们不能使用 Promise.all 来实现。Promise 有一个 allSettled 方法,https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled

Event

发布订阅模式,Node.js 内置events 模块

比如HTTP server on('request') 事件监听

const EventEmitter = require("events");

class MyEmitter extends EventEmitter 

const myEmitter = new MyEmitter();

myEmitter.on("event", () => 
  console.log("an event occurred!");
);
myEmitter.emit("event");

const http = require("http");

const server = http.createServer((req, res) => 
  res.end("hello!!! this is YK!!!");
);
server.on("request", (req, res) => 
  console.log(req.url);
);

server.listen(3000);

参考

  • 字节跳动青训营 PPT + 视频
  • 《深入浅出Node.js》

青训营node.js基础-特点-模块化commonjs&esm-npm包管理(代码片段)

文章目录起步安装与运行版本管理特点异步I/O单线程多进程的浏览器跨平台应用场景模块化机制CommonJS规范机制加载方式npm包查找原则npm缓存其他模块化规范ESModules(ESM)CommonJSVSESMCommonJS:值的**拷贝**ESM:值的**引用**常用... 查看详情

青训营node.js基础-特点-模块化commonjs&esm-npm包管理(代码片段)

文章目录起步安装与运行版本管理特点异步I/O单线程多进程的浏览器跨平台应用场景模块化机制CommonJS规范机制加载方式npm包查找原则npm缓存其他模块化规范ESModules(ESM)CommonJSVSESMCommonJS:值的**拷贝**ESM:值的**引用**常用... 查看详情

青训营node.js基础-web应用开发-开发调试-线上部署(代码片段)

文章目录Web应用开发HTTP模块Koa介绍中间件常用中间件基于Koa的前端框架调试断点调试日志调试线上部署利用多核CPU进程守护复杂计算前端开发与后端开发对比前几天学了一些Node.js的基础,今天来学习Web应用开发,在开发... 查看详情

字节跳动青训营每日一练编程题

1:实现一个36进制的加法0-9a-z。#include<bits/stdc++.h>typedeflonglongll;constllN=2e5+10;usingnamespacestd;ints[N];intmain()int_;stringa,b;while(cin>>a>>b)stringans;intpos 查看详情

青训营pro️从0到1实现一个自己的前端约定路由项目脚手架️工具~(代码片段)

文章目录前言一、Node基础API核心API-无需`require`内置API-需要`require`无需`install`1.fs与异步IO①同步读取文件②异步读取文件③promisify2.buffer与字符集3.http练习1node基础fs\\buffer\\http搭建一个http服务4.stream5.子进程二... 查看详情

青训营pro️从0到1实现一个自己的前端约定路由项目脚手架️工具~(代码片段)

文章目录前言一、Node基础API核心API-无需`require`内置API-需要`require`无需`install`1.fs与异步IO①同步读取文件②异步读取文件③promisify2.buffer与字符集3.http练习1node基础fs\\buffer\\http搭建一个http服务4.stream5.子进程二... 查看详情

字节跳动青训营笔试题解(代码片段)

...圈题目思路代码四、简答题题目思路前言第五届字节跳动青训营-后端专场笔试题解,简单做了一下,选择题和简答题不知道是否正确,编程题是通过了的,有问题欢迎评论,我会及时改正的~一、单选题选AQUIC&... 查看详情

字节跳动青训营笔试题解(代码片段)

...圈题目思路代码四、简答题题目思路前言第五届字节跳动青训营-后端专场笔试题解,简单做了一下,选择题和简答题不知道是否正确,编程题是通过了的,有问题欢迎评论,我会及时改正的~一、单选题选AQUIC&... 查看详情

青训营html基础-语义化标签-浏览器渲染过程-笔记及拓展(代码片段)

...)博主还是很久之前学习的,这次趁着字节跳动青训营的活动,就再学习一遍HTML。一小时的课程,巩固了之前的一些知识,也学到了很多新知识。我把这次课程的内容与我这一年来学习前端的经验相结合,... 查看详情

第五届字节青训营笔试后端编程练习题解(代码片段)

文章目录前言T1.36进制加法(模拟)题面思路代码T2.电影院选座(DFS)题面思路代码T3.IP地址(DFS)题面思路代码前言前段时间🐏了,今天简单写了一下,不知道如何提交代码进行评测,题... 查看详情

go语言上手|青训营笔记(代码片段)

这是我参与「第三届青训营-后端场」笔记创作活动的的第一篇笔记。文章目录语法速览基础语法第一:类型第二:内置库部分json库的使用时间库的使用字符串和数字互转os相关信息实战项目猜谜游戏(pass,过于... 查看详情

青训营月影老师告诉我写好javascript的四大技巧——保证正确(代码片段)

文章目录起步洗牌算法验证正确性解决方案一:多洗几次解决方案二:随机采样应用抽奖分红包总结更多相关博文如何写好JavaScript是每一个前端工程师一直以来在思考的问题,月影老师告诉我们一些写好JavaScript的原... 查看详情

字节跳动青训营每日一练编程题

1:实现一个36进制的加法0-9a-z。#include<bits/stdc++.h>typedeflonglongll;constllN=2e5+10;usingnamespacestd;ints[N];intmain()int_;stringa,b;while(cin>>a>>b)stringans;intpos;reverse(a.begin(),a.end());reverse(b.begin(),b.end());for(inti=0;i<max(a... 查看详情

青训营月影老师告诉我写好javascript的三大原则之——过程抽象(代码片段)

...5.总结过程抽象/HOF/装饰器命令式/声明式参加了这次字节青训营的活动,见到了传说中的月影老师࿰ 查看详情

字节跳动青训营笔试题解(代码片段)

...圈题目思路代码四、简答题题目思路前言第五届字节跳动青训营-后端专场笔试题解,简单做了一下,选择题和简答题不知道是否正确,编程题是通过了的,有问题欢迎评论,我会及时改正的~一、单选题选AQUIC&... 查看详情

结营啦!有缘相聚于青训,未来高处见呀~~(代码片段)

📸叮!记·字节跳动第一届青训营顺利结营啦!从8月份的青训营,到9月份的实训营,搁置了许久的结营心得终于拾起来辽!🎬开营进行时从答疑会开始,负责人仔细的阐述了本次训练营的性质和... 查看详情

node.js--ajax编程基础(代码片段)

文章目录Ajax基础Ajax运行原理及实现XMLHttpRequest对象Ajax的实现步骤服务器端响应的数据格式---JSON请求参数传递GET请求方式POST请求方式请求报文请求参数的格式(包含JSON格式)【案例】向服务器端传递json格式的请求参数... 查看详情

第五届字节青训营笔试后端编程练习题解(代码片段)

文章目录前言T1.36进制加法(模拟)题面思路代码T2.电影院选座(DFS)题面思路代码T3.IP地址(DFS)题面思路代码前言前段时间🐏了,今天简单写了一下,不知道如何提交代码进行评测,题... 查看详情