当前位置: 首页 > 科技观察

JavaScript中回调、Promise和Async-Await的代码示例

时间:2023-03-12 08:06:14 科技观察

本文将通过代码示例展示如何使用基于回调的API,然后将其更改为使用Promises,最后使用Async/Await语法。本文不详细解释回调、承诺和Async/Await语法。有关这些概念的详细解释,请查看MDN的异步JavaScript[1],其中解释了什么是异步性以及如何使用回调、承诺和Async/Await语法处理异步JavaScript。如果您对JavaScript中的异步有一些了解,但需要一个直观的代码示例作为参考,那么本文适合您。出于演示目的,我们将使用fs.readFile[2],这是一个用于读取文件的基于回调的API。我们将首先创建一个包含一些文本的文件test.txt,然后使用script.js打开该文件,读取内容并将其输出到终端。代码会先用回调实现,然后修改为使用Promises,最后改为使用Async/Await,而不是直接使用Promises。废话少说,开始吧!使用回调首先创建一个目录,其中包含我们的代码文件和要读取的文件。首先创建两个文件;$mkdir~/code$touch~/code/script.js$echo"Beammeup,Scotty">~/code/test.txt$cd~/code/script.js文件中,输入如下代码:constfs=require("fs")functionreadFileCallBack(){fs.readFile("./test.txt",'utf8',(err,data)=>{if(err){console.error(err)返回}console.log(data.trim()+[callback]")})}readFileCallBack()通过nodescript.js命令执行脚本,在终端输出"Beammeup,Scotty":$nodescript.jsBeammeup,Scotty[callback]对于回调方法,异步操作的结果会传递给执行异步操作的函数,由其处理。修改script.js以使用承诺并添加一个使用承诺的readFileCallback版本。代码如下:functionreadFilePromise(){returnnewPromise((resolve,reject)=>{fs.readFile("./test.txt",'utf8',(err,data)=>{if(err){reject(err)return}resolve(data.trim())})});}readFilePromise().then(data=>console.log(data+"[promise]")).catch(err=>console.log(err))通过nodescript.js命令执行脚本:$nodescript.jsBeammeup,Scotty[callback]Beammeup,Scotty[promise]使用promises,将异步操作的结果传递给promise对象暴露的then函数进行处理。使用Async/Await修改script.js并添加使用Async/Await语法的第三个版本。由于Async/Await是一种使承诺更容易的语法,因此Async/Await实现将使用readFilePromise()函数。代码是这样的:asyncfunctionreadFileAsync(){try{constdata=awaitreadFilePromise()console.log(data.trim()+"[async-await]")}catch(err){console.log(err)}}readFileAsync()通过运行nodescript.js执行脚本会打印类似这样的东西,到终端:异步操作被视为同步操作。await对此负责,使用它的函数必须以async关键字开头。三个实现的完整代码如下:constfs=require("fs")//callbackfunctionreadFileCallBack(){fs.readFile("./test.txt",'utf8',(err,data)=>{if(err){console.error(err)return}console.log(data.trim()+[callback]")})}readFileCallBack()//promisefunctionreadFilePromise(){returnnewPromise((resolve,reject)=>{fs.readFile("./test.txt",'utf8',(err,data)=>{if(err){reject(err)return}resolve(data.trim())})});}读取文件承诺()。then(data=>console.log(data+[promise]")).catch(err=>console.log(err))//async/awaitasyncfunctionreadFileAsync(){try{constdata=awaitreadFilePromise()console.log(data.trim()+[async-await]")}catch(err){console.log(err)}}readFileAsync()错误处理为了验证错误处理在3个代码实现工作时是否按预期工作,重命名test.txt文件并重新运行脚本:$mvtest.txttest.txt.backup$nodescript.js[Error:ENOENT:nosuchfileordirectory,open'./test.txt']{errno:-2,code:'ENOENT',系统调用:'打开',路径:'./test.txt'}[错误:ENOENT:nosuchfileordirectory,打开'./test.txt']{errno:-2,code:'ENOENT',syscall:'open',path:'./test.txt'}[Error:ENOENT:nosuchfileordirectory,open'./test.txt']{errno:-2,code:'ENOENT',syscall:'open',path:'./test.txt'}三种实现都会显示错误处理代码(只是向控制台输出错误),说明它们都按预期执行