当前位置: 首页 > Web前端 > JavaScript

js异步编程的三种模式_1

时间:2023-03-26 21:18:51 JavaScript

写在前面javascript语言的执行环境是“单线程”(singlethread),也就是一次只能完成一个任务。如果有多个任务,则必须排队,等待上一个任务完成,再执行下一个任务,以此类推。这种模式的优点是实现起来比较简单,执行环境也比较简单;缺点是只要一个任务耗时长,后面的任务就必须排队等候,会延迟整个程序的执行。单线程functionf1(){console.log('1')}functionf2(){console.log('2')}f1()f2()很容易看出上面的代码会输出1和2顺序。因为代码是从上到下顺序执行的,所以f2()会在f1()执行完之后执行。但是如果f1()里面的代码是读取文件或者ajax操作,读取文件需要一定的时间。我们是否需要等到文件完全读取后再写入?为了解决这个问题,我们来探究一下js中同步和异步的概念。同步和异步同步是指在主线程上排队等待执行的任务。只有完成了上一个任务,才能执行下一个任务。也就是说一旦调用开始,调用必须返回一个结果(强调-)才能继续执行。程序的执行顺序与任务的顺序一致。Asynchronous异步任务是指不进入主线程而是进入任务队列的任务。只有当任务队列通知主线程有异步任务可以执行时,任务才会进入主线程。每个任务都有一个或多个回调函数。前一个任务结束后,不执行后一个任务,而是执行回调函数,不等前一个任务结束就执行后一个任务。程序的执行顺序和任务的排列顺序不一致,异步。我们常用的setTimeout和setInterval函数,ajax都是异步操作。那么如何实现异步编程,笔者介绍了回调函数(Callback)回调函数的几种方法,这是异步编程最基本的方法。constfs=require('fs')fs.readFile('./pakage.json',(err,info)=>{fs.writeFile('./p.json',info,(err)=>{如果(!err){setTimeout(()=>{console.log('ok')},2000)}})})上面的代码通过回调函数的嵌套从文件系统中读取了一个./pakage.json文件写入./p.json,读取成功两秒后输出'ok'。使用回调来实现异步没有错。但是试想一下,如果异步函数多了几个,代码整体的可维护性和可读性就会变得极差。如果出现错误,修复过程将变得异常困难。这就是所谓的回调函数地狱。参考视频讲解:进入学习Promise对象Promise对象用于表示一个异步操作的最终状态(完成或失败)及其返回的值。MDN对Promise的定义如上。Promise原意为承诺。我们可以理解为该程序承诺在一段时间后给您一个结果。Promise是一个可以拥有三种状态的对象。每个时刻都必须有一个状态。成功实现失败拒绝处理挂起默认挂起如果调用解决完成默认挂起如果调用拒绝rejectedconstfs=require('fs')constpromise1=newPromise((resolve,reject)=>{fs.readFile('./package.json',(err,info)=>{resolve(info)})})constpromise2=(info)=>{newPromise((resolve,reject)=>{fs.writeFile('./p.json',info,(err)=>{if(!err){resolve();}else{reject();}})})}constpromise3=(time)=>{returnnewPromise((resolve,reject)=>{setTimeout(()=>{resolve()},time)})}//然后链式调用//读取文件成功并将结果作为参数传递给promise2promise1.then((info)=>{returnpromise2(info)}).then(()=>{//等待前面的promiseconsole.log('读写完成')returnpromise3(2000)}).then(()=>{console.log('ok')})这样看,没有区别,比上面的异步回调要复杂一些。您必须先创建一个Promise,然后定义其回调。但实际上,Promise的真正强大之处在于它的多次链式调用,可以避免层层嵌套的回调。我们首先使用new来构造一个promise。Promise接受一个函数作为参数,函数的两个参数是resolve和reject。resolve:成功时调用,结果作为参数传递;reject:失败时调用,并作为参数抛出错误。then方法接收两个函数作为参数,第一个参数是Promise执行成功时的回调,第二个参数是Promise执行失败时的回调。Promise对象的then方法返回一个新的Promise对象,所以then方法可以通过链式调用。我们可以继续优化一点。async+await语法糖直接放在代码上asyncfunctionrun(){letinfo=awaitpromise1;等待promise2(信息);等待promise3(2000);console.log('ok');}ES2017标准中引入了async函数,让我们的异步代码更加优雅。这里使用async+await代替.then()方法。Async必须在函数声明之前等待一个promise,然后下面的代码将等待直到promiseresolve才执行。