JavaScript——异步操作的控制

JavaScript 是一种单线程的语言,这意味着 JavaScript 一次只能执行一个操作。然而,JavaScript 中有很多异步的特性,包括事件处理、定时器、Ajax 请求、Promise、async/await 等机制。

这些异步特性使得 JavaScript 能够处理大量的网络请求、定时任务、用户交互等操作,而不会阻塞程序的执行。通过合理地利用这些异步特性,JavaScript 能够提供更流畅的用户体验,并且能够处理复杂的并发操作。


通过阅读以下几个知识点可以帮助我们理解如何控制异步代码的执行

1. 回调函数

2. Promise对象

3. then方法

4. async/await


回调函数

在 JavaScript 中,回调函数是一种常见的编程模式,用于处理异步操作和事件驱动的代码。回调函数是一个作为参数传递给其他函数的函数,在特定的事件发生或异步操作完成后被调用。

javascript 复制代码
function a(cb){
    setTimeout(()=>{
    console.log('A');
    cb();
    },1000)
}
function b(){
    setTimeout(()=>{
    console.log('B');
    },500)
}
a(b);

在这段代码中,调用 a 函数,并将参数 b 作为回调函数传入。在 a 函数内部,调用 setTimeout 函数并传入一个回调函数和延迟时间为 1000 毫秒。回调函数中打印出字母 'A',然后调用回调函数 cb。回到 a 函数外部,此时 b 函数已经被传入到 a 函数内部。继续执行 b 函数之前,等待 1000 毫秒,即 a 函数内部的 setTimeout 完成后再执行。

通过使用回调函数,可以确保代码在异步操作或事件完成后得到正确的执行顺序。然而,使用过多的回调函数可能会导致代码可读性下降和出现回调地狱的问题,回调地狱会使得代码的维护变得异常的困难。为了解决这个问题,ES6 引入了 Promise 和 async/await 等更高级的异步处理机制。

Promise对象

Promise 是一种用于处理异步操作的对象。Promise 主要用于解决回调地狱和处理异步代码的可读性。

scss 复制代码
function xq(){
    return new Promise((resolve, reject) =>{
        setTimeout(()=>{    //定时器
            console.log('a');
            resolve();// 成功完成异步操作,将数据作为参数传递给 resolve 方法        
            },2000)  //两秒后执行
    })
}
function baby(){
    console.log('c');
}
xq().then(()=>{  //打印a
    baby();      //打印b
});

在上面的示例中,通过 Promise 构造函数创建了一个 Promise 对象,并执行异步操作。当异步操作成功完成时,调用 resolve() 方法将数据作为参数传递给 then 方法中的回调函数。

Promise 对象可以通过调用 then 方法来添加成功处理函数和失败处理函数。then 方法接收两个参数:第一个参数是成功处理函数,第二个参数是失败处理函数。这些处理函数在 Promise 对象状态改变时被调用。

then方法

在 JavaScript 中,then 是 Promise 对象的一个方法,用于指定当 Promise 对象状态变为 resolved(成功)时要执行的回调函数。then 方法接受两个参数:第一个参数是 Promise 成功时执行的回调函数,第二个参数(可选)是 Promise 失败时执行的回调函数。这两个参数都是函数类型。

javascript 复制代码
function xq(){
    return new Promise((resolve, reject) =>{
        setTimeout(()=>{
            console.log('a');
            resolve();// 成功完成异步操作,将数据作为参数传递给 resolve 方法        
            },2000)
    })
}
function marry(){
    return new Promise((resolve, reject) =>{
        setTimeout(()=>{
            console.log('b');
            resolve();
            },1000)
    });
}
function baby(){
    console.log('c');
}
xq().then(()=>{   //打印a
   return marry()
})
.then(()=>{   //打印b
    baby();   //打印c
});

JavaScript是单线程的语言,它在遇到定时器等异步的代码时,会将这个线程挂起然后去执行其他的同步代码。通过使用then方法可将原本会挂起的异步代码立即执行。当异步操作成功完成时,调用 resolve() 方法将数据作为参数传递给 then 方法中的回调函数。

then 方法也返回一个 Promise 对象,因此可以链式调用多个 then 方法来处理一系列异步操作的结果。因此在这段代码中可以实现控制函数的执行顺序做到a,b,c依次打印。

async/awiat

使用 async 关键字声明一个函数时,该函数会返回一个 Promise 对象。在函数体内部,使用 await 关键字可以暂停函数的执行,等待 Promise 对象完成,并返回 Promise 的结果。

javascript 复制代码
async function myAsyncFunction() {
    try {
      const result = await myPromise; // 等待异步操作的结果
      console.log(result);
    } catch (error) {
      console.error(error);
    }
  }
  
  myAsyncFunction();

在上面的代码中,我们使用 async 关键字声明了一个异步函数 myAsyncFunction。在函数体内部,我们使用 await 关键字等待一个返回 Promise 对象的表达式 myPromise。当 myPromise 被解析时,结果会被赋值给 result,然后我们可以在函数中继续处理 result。如果 myPromise 被拒绝,那么错误信息会被捕获并传递给 catch 块进行处理。

使用 async/await 可以让异步代码看起来更像同步代码,使得逻辑更加清晰和易于理解。然而,需要注意的是,await 关键字只能在异步函数内部使用,而且它只能等待返回 Promise 的表达式,因此在使用时需要注意函数的上下文和语法规则。

相关推荐
樱花落木兰3 小时前
分布式登录实战:Session 会话共享改造,Redis 存储用户登录状态
java·javascript·数据库·redis·分布式·缓存
liangshanbo12153 小时前
面试题:线上 JavaScript 报错如何快速定位到源码?
开发语言·javascript·ecmascript
专业程序开发源5 小时前
django新闻推荐系统70655-计算机课程设计、毕业设计
java·javascript·spring boot·后端·python·django·课程设计
acd120095 小时前
前端随笔:数据明明变了,Vue 页面就是不更新
前端·javascript·vue.js
传人7 小时前
悬停旋转放大和位移效果如何写
前端·javascript·css
羲云7 小时前
给 Vue 页面加个 Markdown 编辑器:ME.js 的接入、图片粘贴与音视频
javascript·vue.js
Highcharts.js8 小时前
可视化商用图表库对比,如何选择?
前端·javascript·学习·信息可视化·highcharts·前端可视化
TheITSea9 小时前
JavaScript Web APIs
开发语言·前端·javascript
开开心心就好9 小时前
以图搜图找重复图片,本地工具离线就能用
javascript·智能手机·ffmpeg·c#·ocr·word·音视频
企业数字化笔记9 小时前
视频局部合成怎么做得自然?掩膜修复、边缘羽化、时序稳定与背景替换
java·javascript·音视频