异步编程概述
曾经的单线程模型在同步I/O的影响下,由于I/O调用缓慢,在应用层面导致cpu与I/O无法重叠进行。为了照顾编程人员的阅读思维习惯,同步I/O盛行了很多年。【推荐学习:《nodejs 教程》】
但是有很大的性能问题!
Node利用JavaScript及其内部异步库,将异步直接提升到业务层面。Node带来的最大特性莫过于基于事件驱动的非阻塞I/O模型。非阻塞I/O可以使cpu与I/O并不相互依赖等待,让资源得到更好的利用。
异步编程解决方案
目的:读取package.json 中main 字段对应的文件内容
Callback
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,实现读取 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 方法,developer.mozilla.org/en-US/docs/…
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);
原文地址:https://juejin.cn/post/7005509871000895524
作者:YK菌
更多编程相关知识,请访问:编程视频!!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。