• 售前

  • 售后

热门帖子
入门百科

一文秒懂nodejs中的异步编程

[复制链接]
因醉鞭名马幌 显示全部楼层 发表于 2021-10-25 20:19:51 |阅读模式 打印 上一主题 下一主题
文章目次 简介同步异步和壅闭非壅闭javascript中的回调回调函数的错误处置惩罚回调地狱 ES6中的Promise什么是PromisePromise的特点Promise的长处Promise的缺点Promise的用法Promise的实行序次 async和awaitasync的实行序次async的特点 总结
简介

因为javascript默认情况下是单线程的,这意味着代码不能创建新的线程来并行实行。但是对于最开始在欣赏器中运行的javascript来说,单线程的同步实行情况显然无法满意页面点击,鼠标移动这些相应用户的功能。于是欣赏器实现了一组API,可以让javascript以回调的方式来异步相应页面的哀求变乱。
更进一步,nodejs引入了非壅闭的 I/O ,从而将异步的概念扩展到了文件访问、网络调用等。
今天,我们将会深入的探究一下各种异步编程的优缺点和发展趋势。
同步异步和壅闭非壅闭

在讨论nodejs的异步编程之前,让我们来讨论一个比力轻易肴杂的概念,那就是同步,异步,壅闭和非壅闭。
所谓壅闭和非壅闭是指历程大概线程在举行操作大概数据读写的时候,是否必要等候,在等候的过程中能否举行其他的操作。
如果必要等候,而且等候过程中线程或历程无法举行其他操作,只能傻傻的等候,那么我们就说这个操作是壅闭的。
反之,如果历程大概线程在举行操作大概数据读写的过程中,还可以举行其他的操作,那么我们就说这个操作黑白壅闭的。
同步和异步,是指访问数据的方式,同步是指必要主动读取数据,这个读取过程大概是壅闭大概黑白壅闭的。而异步是指并不必要主动去读取数据,是被动的关照。
很显着,javascript中的回调是一个被动的关照,我们可以称之为异步调用。
javascript中的回调

javascript中的回调是异步编程的一个非常范例的例子:
  1. document.getElementById('button').addEventListener('click', () => {
  2. console.log('button clicked!');
  3. })
复制代码
上面的代码中,我们为button添加了一个click变乱监听器,如果监听到了click变乱,则会出发回调函数,输出相应的信息。
回调函数就是一个平凡的函数,只不外它被作为参数传递给了addEventListener,而且只有变乱触发的时候才会被调用。
上篇文章我们讲到的setTimeout和setInterval现实上都是异步的回调函数。
回调函数的错误处置惩罚

在nodejs中怎么处置惩罚回调的错误信息呢?nodejs采用了一个非常巧妙的办法,在nodejs中,任何回调函数中的第一个参数为错误对象,我们可以通过判定这个错误对象的存在与否,来举行相应的错误处置惩罚。
  1. fs.readFile('/文件.json', (err, data) => {
  2. if (err !== null) {
  3. //处理错误
  4. console.log(err)
  5. return
  6. }
  7. //没有错误,则处理数据。
  8. console.log(data)
  9. })
复制代码
回调地狱

javascript的回调固然非常的优秀,它有效的办理了同步处置惩罚的题目。但是遗憾的是,如果我们必要依赖回调函数的返回值来举行下一步的操作的时候,就会陷入这个回调地狱。
叫回调地狱有点浮夸了,但是也是从一方面反映了回调函数所存在的题目。
  1. fs.readFile('/a.json', (err, data) => {
  2. if (err !== null) {
  3. fs.readFile('/b.json',(err,data) =>{
  4.   //callback inside callback
  5. })
  6. }
  7. })
复制代码
怎么办理呢?
别怕ES6引入了Promise,ES2017引入了Async/Await都可以办理这个题目。
ES6中的Promise

什么是Promise

Promise 是异步编程的一种办理方案,比传统的办理方案“回调函数和变乱”更公道和更强盛。
所谓Promise,简单说就是一个容器,内里保存着某个将来才会结束的变乱(通常是一个异步操作)的效果。
从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
Promise的特点

Promise有两个特点:
对象的状态不受外界影响。
Promise对象代表一个异步操作,有三种状态:Pending(举行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败)。
只有异步操作的效果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
一旦状态改变,就不会再变,任何时候都可以得到这个效果。
Promise对象的状态改变,只有两种大概:从Pending变为Resolved和从Pending变为Rejected。
这与变乱(Event)完全不同,变乱的特点是,如果你错过了它,再去监听,是得不到效果的。
Promise的长处

Promise将异步操作以同步操作的流程表达出来,制止了层层嵌套的回调函数。
Promise对象提供统一的接口,使得控制异步操作更加轻易。
Promise的缺点

      
  • 无法取消Promise,一旦新建它就会立刻实行,无法中途取消。  
  • 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。  
  • 当处于Pending状态时,无法得知目前希望到哪一个阶段(刚刚开始照旧即将完成)。
Promise的用法

Promise对象是一个构造函数,用来天生Promise实例:
  1. var promise = new Promise(function(resolve, reject) {
  2. // ... some code
  3. if (/* 异步操作成功 */){
  4. resolve(value);
  5. } else { reject(error); }
  6. }
  7. );
复制代码
promise可以接then操作,then操作可以接两个function参数,第一个function的参数就是构建Promise的时候resolve的value,第二个function的参数就是构建Promise的reject的error。
  1. promise.then(function(value) {
  2. // success
  3. }, function(error) {
  4. // failure }
  5. );
复制代码
我们看一个具体的例子:
  1. function timeout(ms){
  2. return new Promise(((resolve, reject) => {
  3.   setTimeout(resolve,ms,'done');
  4. }))
  5. }
  6. timeout(100).then(value => console.log(value));
复制代码
Promise中调用了一个setTimeout方法,并会定时触发resolve方法,并传入参数done。
最后步伐输出done。
Promise的实行序次

Promise一经创建就会立马实行。但是Promise.then中的方法,则会比及一个调用周期过后再次调用,我们看下面的例子:
  1. let promise = new Promise(((resolve, reject) => {
  2. console.log('Step1');
  3. resolve();
  4. }));
  5. promise.then(() => {
  6. console.log('Step3');
  7. });
  8. console.log('Step2');
  9. 输出:
  10. Step1
  11. Step2
  12. Step3
复制代码
async和await

Promise当然很好,我们将回调地狱转换成了链式调用。我们用then来将多个Promise毗连起来,前一个promise resolve的效果是下一个promise中then的参数。
链式调用有什么缺点呢?
好比我们从一个promise中,resolve了一个值,我们必要根据这个值来举行一些业务逻辑的处置惩罚。
如果这个业务逻辑很长,我们就必要在下一个then中写很长的业务逻辑代码。这样让我们的代码看起来非常的冗余。
那么有没有什么办法可以直接返回promise中resolve的效果呢?
答案就是await。
当promise前面加上await的时候,调用的代码就会停止直到 promise 被办理或被拒绝。
注意await一定要放在async函数中,我们来看一个async和await的例子:
  1. const logAsync = () => {
  2. return new Promise(resolve => {
  3. setTimeout(() => resolve('小马哥'), 5000)
  4. })
  5. }
复制代码
上面我们界说了一个logAsync函数,该函数返回一个Promise,因为该Promise内部利用了setTimeout来resolve,所以我们可以将其看成是异步的。
要是利用await得到resolve的值,我们必要将其放在一个async的函数中:
  1. const doSomething = async () => {
  2. const resolveValue = await logAsync();
  3. console.log(resolveValue);
  4. }
复制代码
async的实行序次

await现实上是去等候promise的resolve效果我们把上面的例子结合起来:
  1. const logAsync = () => { return new Promise(resolve => {  setTimeout(() => resolve('小马哥'), 1000) })}const doSomething = async () => {
  2. const resolveValue = await logAsync();
  3. console.log(resolveValue);
  4. }console.log('before')doSomething();console.log('after')
复制代码
上面的例子输出:
  1. before
  2. after
  3. 小马哥
复制代码
可以看到,aysnc是异步实行的,而且它的序次是在当前这个周期之后。
async的特点

async会让全部背面接的函数都酿成Promise,纵然背面的函数没有表现的返回Promise。
  1. const asyncReturn = async () => {
  2. return 'async return'
  3. }
  4. asyncReturn().then(console.log)
复制代码
因为只有Promise才华在背面接then,我们可以看出async将一个平凡的函数封装成了一个Promise:
  1. const asyncReturn = async () => {
  2. return Promise.resolve('async return')
  3. }
  4. asyncReturn().then(console.log)
复制代码
总结

promise制止了回调地狱,它将callback inside callback改写成了then的链式调用情势。
但是链式调用并不方便阅读和调试。于是出现了async和await。
async和await将链式调用改成了雷同步伐序次实行的语法,从而更加方便理解和调试。
我们来看一个对比,先看下利用Promise的情况:
  1. const getUserInfo = () => {
  2. return fetch('/users.json') // 获取用户列表
  3. .then(response => response.json()) // 解析 JSON
  4. .then(users => users[0]) // 选择第一个用户
  5. .then(user => fetch(`/users/${user.name}`)) // 获取用户数据
  6. .then(userResponse => userResponse.json()) // 解析 JSON
  7. }
  8. getUserInfo()
复制代码
将其改写成async和await:
  1. const getUserInfo = async () => {
  2. const response = await fetch('/users.json') // 获取用户列表
  3. const users = await response.json() // 解析 JSON
  4. const user = users[0] // 选择第一个用户
  5. const userResponse = await fetch(`/users/${user.name}`) // 获取用户数据
  6. const userData = await userResponse.json() // 解析 JSON
  7. return userData
  8. }
  9. getUserInfo()
复制代码
可以看到业务逻辑变得更加清楚。同时,我们获取到了许多中间值,这样也方便我们举行调试。
到此这篇关于深入理解nodejs中的异步编程的文章就先容到这了,更多相关nodejs异步编程内容请搜刮脚本之家从前的文章或继承欣赏下面的相关文章盼望大家以后多多支持脚本之家!

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作