首页 > 编程语言 >用async/await改造Node.js(Express)网站

用async/await改造Node.js(Express)网站

时间:2024-04-07 18:00:30浏览次数:12  
标签:Node function await err Express asyncReadFile var async

用async/await改造Node.js(Express)网站

Mike的读书季IP属地: 北京 2018.11.02 00:13:00字数 582阅读 3,115

1.回调的嵌套陷阱

在Node.js中,使用回调的方式进行异步操作,我们以读取文件内容为例:

const fs = require('fs');

// 定义一个以回调的方式获取文件的函数
function asyncReadFile(path, callback) {
    fs.readFile(path, 'utf-8', function(err, data) {
        callback(err,data)
    })
}

// 调用:
router.get('/', async function(req, res, next) {
    asyncReadFile("./package.json", (err, data) {
        console.log(data)
        // 渲染页面
        res.render('index', { title: 'Express' });
    })
})

从上面的调用不难推测出,以回调的方式来实现异步,嵌套将会是开发者的噩梦:

router.get('/', async function(req, res, next) {
    asyncReadFile("./package.json", (err, data1) {
        console.log(data1)
        asyncReadFile("./app.js", (err, data2) {
            console.log(data2)
            asyncReadFile("./other.js", (err, data3) {
                console.log(data3)
                // ...
                
                // 渲染页面
                res.render('index', { title: 'Express' });
            })
        })
    })
})

在业务查询比较多、需要同时触发的任务中,回调会严重影响排版及阅读,尤其对接手人(甚至开发者自己)的阅读和理解造成了很大的困难。

2.使用async/await

接下来,我将改造上面的 asyncReadFile() 函数,以将返回值其构造为 Promise 对象。

var fs = require('fs')

var asyncReadFile = function(path) {
    return new Promise(function(resolve, reject) {
        fs.readFile(path, 'utf-8', function(err, data) {
            resolve(data)
        })
    })
}

router.get('/', async function(req, res, next) {
    var file = await asyncReadFile("./package.json")
    console.log(file)
    // 渲染
    res.render('index', { title: 'Express' });
});

这里需要注意的是,async 和 await 是成对出现的。即你要在哪个函数使用 await 的方式,就应当对这个函数进行 async 声明。

事实上,这个声明是一种语法糖,即在不改变语法的基础上,让代码的可读性更好、更不容易出错。async就是Generator函数的语法糖。

Generator函数的用法是这样的:

var gen = function* (){
  var f1 = yield readFile('/etc/fstab');
  var f2 = yield readFile('/etc/shells');
};

对应的async用法则是:

var gen = async function (){
  var f1 = await readFile('/etc/fstab');
  var f2 = await readFile('/etc/shells');
};

即将 * 和 yield 分别用 async 和 await 替换了。

语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。

3.处理reject()

在函数中添加 reject() 的调用,并在Promise对象后面追加一个 .catch() 的处理

var fs = require('fs')

var asyncReadFile = function(path) {
    return new Promise(function(resolve, reject) {
        fs.readFile(path, 'utf-8', function(err, data) {
            if(err) {
                reject(err)
            }
            resolve(data)
        })
    })
    // This must be called in case of node-process terminated by reject()
    .catch((err)=>{
        return err
    })
}

router.get('/', async function(req, res, next) {
    var file = await asyncReadFile("./package.json")
    console.log(file)
    // 渲染
    res.render('index', { title: 'Express' });
});

或者在调用的时候 catch 错误

var fs = require('fs')

var asyncReadFile = function(path) {
    return new Promise(function(resolve, reject) {
        fs.readFile(path, 'utf-8', function(err, data) {
            if(err) {
                reject(err)
            }
            resolve(data)
        })
    })
}

router.get('/', async function(req, res, next) {
    try {
        var file = await asyncReadFile("./package.json")
        console.log(file)
    }catch (e) {
        console.error(e);
    }
    // 渲染
    res.render('index', { title: 'Express' });
});

此外,需要注意的是,一旦 reject() 执行,后面的代码就立即停止了。

async function func() {
  await Promise.reject(err);
  await Promise.resolve(); // 不会执行
}

4.多个await函数的并发

如果由多个await函数要一起执行,且没有先后关系,可以让它们同时执行,原型为:

var [f1, f2, ...] = await Promise.all([func1, func2, ...])
var [f1, f2] = await Promise.all([
    asyncReadFile("./app.js"),
    asyncReadFile("./package.json")
])

结果集中 f1 即 asyncReadFile("./app.js") 的返回值, f2 即 asyncReadFile("./package.js") 的返回值。


参考资料:
《ECMAScript6笔记:异步操作和Async函数》

标签:Node,function,await,err,Express,asyncReadFile,var,async
From: https://www.cnblogs.com/sexintercourse/p/18119608

相关文章

  • node 建立一个electron的hello world 的工程 有窗体const { app, BrowserWindow } = r
     要创建一个Electron的"HelloWorld"工程,可以按照以下步骤进行:首先,确保你已经安装了Node.js。使用命令行工具进入你要创建项目的目录。运行以下命令来初始化一个新的Node.js项目:bash|npminit-y这将创建一个默认的package.json文件。确保你......
  • NodeJs进阶开发、性能优化指南
    相信对于前端同学而言,我们去开发一个自己的简单后端程序可以借助很多的nodeJs的框架去进行快速搭建,但是从前端面向后端之后,我们会在很多方面会稍显的有些陌生,比如性能分析,性能测试,内存管理,内存查看,使用C++插件,子进程,多线程,Cluster模块,进程守护管理等等NodeJs后端的知识,在这里为大......
  • node.js常用指令
    1、node:启动Node.jsREPL(交互式解释器)。node2、node[文件名]:执行指定的JavaScript文件。nodeapp.js3、npminit:初始化一个新的Node.js项目,生成package.json文件。此命令会创建一个package.json文件,其中包含项目的名称、版本、描述等信息,并且可以选择添加一些默......
  • Do not nest ternary expressions no-nested-ternary 这个报错什么意思
    ESLint规则no-nested-ternary当检测到代码中存在嵌套的三元表达式时,会发出警告或错误。该规则旨在通过禁止使用嵌套的三元表达式来提升代码的可读性和可维护性,因为随着条件复杂度的增加,深度嵌套的三元表达式往往会变得难以理解和推理。三元表达式:三元表达式是JavaScript中一......
  • 基于 bindview.js + node + mysql 的简易记账系统
    该项目前端是基于bindview.js和bootcss,后端的基于node.js使用了express框架,数据库使用的mysql8 bindview: bronze-ding/bindview:Bindview.js,是一个使用虚拟DOM来创建真实DOM并提供了数据响应式的Javascript工具库(github.com)功能包括:增加,删除,修改,查询登录......
  • 如何在 Node.js 中使用 bcrypt 对密码进行哈希处理
    在网页开发领域中,安全性至关重要,特别是涉及到用户凭据如密码时。在网页开发中至关重要的一个安全程序是密码哈希处理。密码哈希处理确保明文密码在数据库受到攻击时也难以被攻击者找到。但并非所有的哈希方法都是一样的,这就是bcrypt突出之处所在。Node.js是一个流行的用于开......
  • Node.js毕业设计基于的动物救助系统(Express+附源码)
    本系统(程序+源码)带文档lw万字以上  文末可获取本课题的源码和程序系统程序文件列表系统的选题背景和意义选题背景:在现代社会中,动物保护已经成为了一个全球性的议题。随着人类社会的发展,动物的生存环境受到了严重的威胁,许多动物面临着生存危机。因此,建立一个有效的动物救......
  • Node.js毕业设计基于的动漫视频管理分析系统的设计与实现(Express+附源码)
    本系统(程序+源码)带文档lw万字以上  文末可获取本课题的源码和程序系统程序文件列表系统的选题背景和意义选题背景:在当今数字化时代,动漫产业作为文化产业的重要组成部分,受到了广大年轻人的热爱和追捧。随着互联网的普及,越来越多的人选择在线观看动漫视频,这为动漫视频管理......
  • DevExpress WinForms中文教程 - 如何通过UI测试自动化增强应用可靠性?(一)
    DevExpressWinForm拥有180+组件和UI库,能为WindowsForms平台创建具有影响力的业务解决方案。DevExpressWinForm能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任!UI自动化测试利用特定的工具/框架来模拟用户与界面的......
  • (免费赠源码)计算机毕设题目:基于微信小程序的旅游服务系统 77397(开题答辩+程序定制+全套
    springboot旅游服务系统小程序摘 要随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,旅游服务系统小程序管理系统被用户普遍使用,为方便用户能够可以随时进行旅游服务系统小......