27 JavaScript学习:异步编程

异步的概念

在JavaScript中,异步编程是一项重要的概念,特别在处理用户交互、网络请求和文件读写等场景下非常常见。JavaScript是一门单线程语言,因此需要通过异步编程来避免阻塞主线程,保证程序的流畅性和响应性。
在这里插入图片描述

在JavaScript中实现异步编程有几种方式:

  1. 回调函数(Callbacks): 回调函数是最基本的异步编程模式,通过在一个函数执行完毕后调用另一个函数来处理结果。例如,在Ajax请求中经常使用回调函数来处理服务器端的响应。

  2. Promise: Promise是ES6引入的一种处理异步操作的方法。使用Promise可以更清晰地表达异步操作的结果,并且可以链式调用多个操作。

  3. Async/Await: Async/Await是ES8引入的语法糖,用于简化Promise的操作。通过async关键字定义的函数可以使用await关键字等待异步操作的结果,使代码看起来更加同步。

  4. 事件监听(Event listeners): 通过事件监听器可以实现订阅发布模式,当某个事件发生时再执行相应的操作。这种模式在处理用户交互或者计时器等场景下非常有用。

  5. Generator函数: Generator函数也可以实现异步操作,通过yield关键字可以暂停函数的执行,然后通过.next()方法继续执行。结合Promise可以完成复杂的异步操作。

总的来说,在JavaScript中实现异步操作是为了避免阻塞主线程,提高程序的性能和响应速度。不同的异步编程方式适用于不同的场景,开发者可以根据具体需求来选择适合的方法。

异步使用场景

JavaScript中异步编程的常见使用场景包括:

  1. 网络请求: 在进行Ajax、Fetch等网络请求时,需要使用异步操作来处理响应,否则主线程将被阻塞。

  2. 文件I/O: 读写文件是一种耗时的操作,使用异步I/O可以避免阻塞主线程。

  3. 定时器: 使用setTimeout和setInterval等函数实现的定时器是异步的,它们不会阻塞主线程的执行。

  4. 事件处理: 在处理用户交互事件(点击、滚动、键盘输入等)时,需要使用事件监听的异步方式。

  5. 数据流处理: 流式数据处理(如视频、音频)通常使用异步的方式来处理数据块,以保证程序的响应性。

  6. 任务队列: 在Web Worker或Node.js中,可以把耗时的任务放到任务队列中异步执行,减轻主线程负担。

  7. 消息队列: 消息队列是一种常见的异步通信机制,用于解耦不同服务或模块之间的依赖关系。

  8. 数据库操作: 与数据库的交互通常是异步进行的,以免阻塞主线程。

  9. 机器学习/数据分析: 复杂的计算任务可以采用异步方式执行,避免影响用户体验。

总的来说,异步编程是JavaScript应对I/O密集型任务的重要手段,可以大幅提高程序的性能和响应能力。合理利用异步机制是编写高质量JavaScript应用程序的关键所在。

回调函数

回调函数是一种常见的异步编程模式,在JavaScript中被广泛使用。回调函数本质上是一个函数,作为参数传递给另一个函数,当特定事件发生或者异步操作完成时,这个回调函数会被执行。

以下是回调函数的一些重要特点和使用场景:

特点:

  1. 异步操作处理: 回调函数通常用于处理异步操作的结果,例如Ajax请求、定时器等。
  2. 事件处理: 在事件监听器中,通常也会使用回调函数来处理特定事件的触发。
  3. 数据传递: 回调函数可以接收参数,用来传递数据给回调函数进行处理。

使用场景:

  1. Ajax请求:

    function fetchData(callback) {// 模拟Ajax请求setTimeout(() => {const data = 'Some data';callback(data);}, 1000);
    }fetchData((data) => {console.log('Data received:', data);
    });
    
  2. 事件处理:

    document.getElementById('myButton').addEventListener('click', () => {console.log('Button clicked');
    });
    
  3. 定时器:

    setTimeout(() => {console.log('Timeout executed');
    }, 2000);
    
  4. Node.js中的文件I/O:

    const fs = require('fs');fs.readFile('data.txt', 'utf8', (err, data) => {if (err) throw err;console.log(data);
    });
    

回调函数是一种灵活且强大的工具,能够帮助处理各种异步操作和事件。然而,过多的回调函数嵌套容易导致"回调地狱",不利于代码的维护和阅读。因此,后续的Promise、Async/Await等方式的出现也是为了解决这一问题。

异步Ajax

在这里插入图片描述

异步Ajax是一种常见的前端编程技术,用于在网页中发送异步请求并处理响应,而不会阻塞页面的加载和用户交互。通过回调函数,可以在Ajax请求完成后执行特定的操作。

下面是一个使用回调函数处理异步Ajax请求的示例:

function fetchData(url, callback) {var xhr = new XMLHttpRequest();xhr.onreadystatechange = function() {if (xhr.readyState === XMLHttpRequest.DONE) {if (xhr.status === 200) {// 请求成功,调用回调函数并传递响应数据callback(null, xhr.responseText);} else {// 请求失败,调用回调函数并传递错误信息callback(new Error('Ajax request failed'));}}};xhr.open('GET', url, true);xhr.send();
}// 调用fetchData函数并传入回调函数处理响应
fetchData('https://api.example.com/data', function(err, data) {if (err) {console.error('Error:', err.message);} else {console.log('Data received:', data);}
});

在这个例子中,fetchData函数接受一个URL和一个回调函数作为参数。当Ajax请求完成后,回调函数会被调用,根据请求的结果执行相应的操作。如果请求成功,回调函数会将错误参数设为null,并传递响应数据;如果请求失败,回调函数会将错误信息传递给第一个参数,并将数据参数设为undefined。

Promise

Promise是一种用于处理JavaScript异步操作的对象,它代表了一个异步操作的最终完成或失败,并返回相应的结果。Promise对象有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。一旦Promise状态发生改变,就会执行相应的回调函数。

使用Promise可以改善回调地狱(callback hell)问题,使代码更易读、更可维护。Promise提供了链式调用的方式来处理异步操作,避免了深层嵌套的回调函数。

一个简单的Promise示例如下:

// 创建一个Promise对象
let myPromise = new Promise((resolve, reject) => {// 异步操作,例如Ajax请求setTimeout(() => {let data = 'Promise resolved data';if (data) {resolve(data); // 异步操作成功,调用resolve并传递数据} else {reject('Promise rejected'); // 异步操作失败,调用reject并传递错误信息}}, 2000);
});// 处理Promise对象的状态
myPromise.then((data) => {console.log('Promise resolved:', data); // 异步操作成功
}).catch((error) => {console.error('Promise rejected:', error); // 异步操作失败
});

在上面的示例中,首先创建了一个Promise对象myPromise,在Promise的executor函数中进行了一个模拟的异步操作,并根据操作结果调用resolvereject方法。接着通过.then()方法处理异步操作成功的情况,通过.catch()方法处理异步操作失败的情况。这样可以清晰地表示异步操作的成功和失败,并链式调用不同的操作。

Promise 的构造函数

Promise构造函数是Promise的一个内置属性,用于创建一个新的Promise对象。它接受一个参数,这个参数是一个函数,也称为"executor"。

Promise构造函数的语法如下:

new Promise(executor);

其中,executor是一个函数,它接受两个参数resolvereject,分别是两个回调函数,用于改变Promise对象的状态。

下面是一个简单的例子:

// 创建一个Promise对象
let myPromise = new Promise((resolve, reject) => {// 异步操作if (/* 异步操作成功 */) {resolve('操作成功'); // 使用resolve改变Promise对象的状态为fulfilled} else {reject('操作失败'); // 使用reject改变Promise对象的状态为rejected}
});

在上面的例子中,executor函数中包含了一个异步操作,根据操作的结果调用resolvereject来改变Promise对象的状态。如果异步操作成功,则调用resolve方法并传递操作成功的结果;如果异步操作失败,则调用reject方法并传递错误信息。

需要注意的是,executor函数在创建Promise对象时立即执行,并且只会执行一次。在executor函数中进行的异步操作可能需要一些时间来完成,而Promise则会立即返回一个pending状态的对象,并在异步操作完成后改变状态。

Promise 使用

当然,下面是一个使用Promise的综合示例列表:

  1. 基本示例:创建一个简单的Promise对象,根据条件决定是解决还是拒绝Promise。
const myPromise = new Promise((resolve, reject) => {const condition = true;if (condition) {resolve("操作成功");} else {reject("操作失败");}
});myPromise.then((message) => {console.log(message);
}).catch((error) => {console.error(error);
});
  1. 异步示例:模拟一个异步操作,并使用Promise来处理成功和失败的情况。
const asyncOperation = () => {return new Promise((resolve, reject) => {setTimeout(() => {const success = true;if (success) {resolve("异步操作成功");} else {reject("异步操作失败");}}, 2000);});
};asyncOperation().then((message) => {console.log(message);
}).catch((error) => {console.error(error);
});
  1. Promise链:使用Promise链来依次执行多个异步操作。
const firstAsyncOperation = () => {return new Promise((resolve) => {setTimeout(() => {resolve("第一个异步操作完成");}, 1000);});
};const secondAsyncOperation = () => {return new Promise((resolve) => {setTimeout(() => {resolve("第二个异步操作完成");}, 1500);});
};firstAsyncOperation().then((message) => {console.log(message);return secondAsyncOperation();}).then((message) => {console.log(message);});

这些是一些简单的Promise示例,展示了如何创建、使用和组合Promise对象来处理异步操作。

回答常见的问题(FAQ)

Q: then、catch 和 finally 序列能否顺序颠倒?

A: 可以,效果完全一样。但不建议这样做,最好按 then-catch-finally 的顺序编写程序。

Q: 除了 then 块以外,其它两种块能否多次使用?

A: 可以,finally 与 then 一样会按顺序执行,但是 catch 块只会执行第一个,除非 catch 块里有异常。所以最好只安排一个 catch 和 finally 块。

Q: then 块如何中断?

A: then 块默认会向下顺序执行,return 是不能中断的,可以通过 throw 来跳转至 catch 实现中断。

Q: 什么时候适合用 Promise 而不是传统回调函数?

A: 当需要多次顺序执行异步操作的时候,例如,如果想通过异步方法先后检测用户名和密码,需要先异步检测用户名,然后再异步检测密码的情况下就很适合 Promise。

Q: Promise 是一种将异步转换为同步的方法吗?

A: 完全不是。Promise 只不过是一种更良好的编程风格。

Q: 什么时候我们需要再写一个 then 而不是在当前的 then 接着编程?

A: 当你又需要调用一个异步任务的时候。

异步函数

在JavaScript中,异步函数可以通过asyncawait关键字来定义和使用。异步函数通常与Promise对象结合使用,以便处理异步操作并获取结果。下面我将详细解释异步函数的用法,并举例说明。

异步函数的定义

在JavaScript中,使用async关键字定义一个异步函数。异步函数可以包含异步操作,并在需要时暂停执行并等待结果。例如:

async function fetchData() {return fetch('https://api.example.com/data');
}

异步函数的调用

要调用异步函数并等待其结果,可以使用await关键字。await只能在异步函数内部使用,用于暂停函数的执行直到异步操作完成并返回结果。例如:

async function displayData() {const response = await fetchData();const data = await response.json();console.log(data);
}displayData();

异步函数的错误处理

异步函数中发生的错误可以通过try...catch语句捕获和处理。例如:

async function fetchData() {try {const response = await fetch('https://api.example.com/data');const data = await response.json();console.log(data);} catch (error) {console.error('Error fetching data:', error);}
}
fetchData();

示例:

下面是一个简单的示例,演示了如何使用异步函数从API获取数据并显示在页面上:

async function fetchData() {const response = await fetch('https://api.example.com/data');const data = await response.json();return data;
}async function displayData() {try {const data = await fetchData();document.getElementById('result').innerText = JSON.stringify(data);} catch (error) {console.error('Error fetching and displaying data:', error);}
}displayData();

以上就是JavaScript中异步函数的概念、定义和用法,

关注我,不迷路,共学习,同进步

关注我,不迷路,共学习,同进步

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/320106.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用SSH密钥克隆仓库

1.创建SSH Key 在用户目录下查看有没有.ssh目录。如果有且该.ssh目录下有id_rsa(私钥),和id_rse_pub(公钥)这俩文件,那么这一步就可以跳过。否则使用以下指令创建SSH Key ssh-keygen -t rsa -C "xxxqq.com" "xx…

时钟基础知识

本文旨在深入浅出地介绍时钟的基础知识,从时间的起源、计量单位到时钟的发展历史,再到现代时钟的种类与功能,全面展现时间如何被人类精确计量与展现。我们将探讨时钟的基本原理,包括机械时钟、石英时钟以及现代电子时钟的运作机制…

图像分割入门-Unet++理论与实践

探索 U-net:改进的图像分割神经网络 引言 图像分割是计算机视觉领域中的重要任务,旨在将图像中的每个像素分配到特定的类别或区域。在许多应用中,如医学影像分析、自动驾驶和地块识别等领域,图像分割都扮演着关键角色。 U-net …

LLMs:《Better Faster Large Language Models via Multi-token Prediction》翻译与解读

LLMs:《Better & Faster Large Language Models via Multi-token Prediction》翻译与解读 目录 《Better & Faster Large Language Models via Multi-token Prediction》翻译与解读 Abstract 2、Method方法 Memory-efficient implementation 高效内存实…

【Mac】 DSync for mac(文件比较同步工具) v2.7安装教程

软件介绍 DSync是一款文件比较同步工具,通过简便的三步即可完成繁琐的比较、同步操作,您甚至可以通过跳过、删除或反转您选择的文件的复制方向来微调您的同步。这是在Mac上同步文件的最简单方法。 安装教程 1.打开安装包,将「DSync」拖到右…

机器学习入门之模型性能评估与度量

文章目录 性能评估误差欠拟合和过拟合模型选择与数据拟合 性能度量二分类的混淆矩阵查全率查准率F1分数 P-R曲线ROC曲线AUC 性能评估 机器学习的模型有很多,我们在选择的时候就需要对各个模型进行对比,这时候就需要一个靠谱的标准,能够评估模…

我们说的数据分析,到底要分析些什么?

作者 Gam 本文为CDA志愿者投稿作品 “我们说数据分析,到底要分析些什么?” 数据分析这个话题自从进入人们的视线以来,这个话题就成为人们茶余饭后的谈资,但是一千个人眼中就有一千个哈姆雷特,就意味着每个人对数据分…

如何将 redis 快速部署为 docker 容器?

部署 Redis 作为 Docker 容器是一种快速、灵活且可重复使用的方式,特别适合开发、测试和部署环境。本文将详细介绍如何将 Redis 部署为 Docker 容器,包括 Docker 安装、Redis 容器配置、数据持久化、网络设置等方面。 步骤 1:安装 Docker 首…

Java 函数式编程 的基础使用2-BiConsumer

1、创建函数时&#xff0c;确定函数的参数类型和具体操作。 2、使用accept接收函数参数&#xff0c;并执行函数操作。 public class MyBiConsumer {public static void main(String[] args) {BiConsumer<String, Integer> printNameAndAge (param1, param2) -> {Sys…

国内首个图计算平台团体标准发布,创邻科技参与编撰

2024年&#xff0c;由中国通信标准协会批准的团体标准《大数据 图计算平台技术要求与测试方法》&#xff08;编号&#xff1a;T/CCSA 470—2023&#xff09;&#xff08;下称&#xff1a;标准&#xff09;正式实施。该标准于1月4日在全国团体标准信息平台&#xff08;https://w…

Golang | Leetcode Golang题解之第59题螺旋矩阵II

题目&#xff1a; 题解&#xff1a; func generateMatrix(n int) [][]int {matrix : make([][]int, n)for i : range matrix {matrix[i] make([]int, n)}num : 1left, right, top, bottom : 0, n-1, 0, n-1for left < right && top < bottom {for column : lef…

触发器的启用和禁用

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 在 Oracle 数据库中&#xff0c;所创建的触发器可以根据情况&#xff0c;灵活修改它的状态&#xff0c;使其有效或者无效&#xff0c;即启用或者禁用。 其语法格式如下所示。…

前端基础学习html(2)

目录 表格标签&#xff1a; 列表标签&#xff1a; 表格标签&#xff1a; <!-- 表格基本架构 --><!-- tr表示一行&#xff0c;td表示一行内单元格 --><!--th为第一行表头加粗居中显示 --><table border"1"><thead><tr><th&g…

[Kubernetes] 安装KubeSphere

选择4核8G&#xff08;master&#xff09;、8核16G&#xff08;node1&#xff09;、8核16G&#xff08;node2&#xff09; 三台机器&#xff0c;按量付费进行实验&#xff0c;CentOS7.9安装Docker安装Kubernetes安装KubeSphere前置环境: nfs和监控安装KubeSphere masternode1no…

RTSP,RTP,RTCP

机器学习 Machine Learning&#xff08;ML&#xff09; 深度学习&#xff08;DL&#xff0c;Deep Learning&#xff09; CV计算机视觉&#xff08;computer vision&#xff09; FFMPEG&#xff0c;MPEG2-TS,H.264,H.265,AAC rstp,rtp,rtmp,webrtc onvif,gb28181 最详细的音…

leetCode76. 最小覆盖子串

leetCode76. 最小覆盖子串 题目思路 代码 // 双指针 哈希表 // 这里cnt维护过程&#xff1a;先找到能够匹配T字符串的滑动窗口&#xff0c;然后这个cnt就固定了&#xff0c;因为i向前移动的同时&#xff0c;j也会维护着向前 // 就是当又出现能够满足T字符串的时候&#xff0…

如何提升制造设备文件汇集的可靠性和安全性?

制造设备文件汇集通常指的是将与制造设备相关的各种文档和资料进行整理和归档的过程。这些文件可能包括但不限于&#xff1a; 生产数据&#xff1a;包括生产计划、订单信息、生产进度等。 设计文件&#xff1a;如CAD图纸、设计蓝图、产品模型等。 工艺参数&#xff1a;用于指…

揭秘设计师热议的7款XD插件!

Adobe XD软件具有从照片编辑和合成到数字绘画、动画和UI设计的一流优势。借助其功能&#xff0c;您可以在灵感来袭时随时随地创建它。令人惊讶的是&#xff0c;它的插件有1000&#xff0c;包括一键磨皮、一键挖掘、一键制作身份证照片等&#xff0c;无论创作什么&#xff0c;Ad…

《十六》QT TCP协议工作原理和实战

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍如何运用QTcpSocket组件实现基于TCP的网络通信…

FIFO Generate IP核使用——异步复位

FIFO Generator IP核提供了一个复位输入&#xff0c;当该输入被激活时&#xff0c;它会复位所有的计数器和输出寄存器。对于块RAM或分布式RAM实现&#xff0c;复位FIFO并不是必需的&#xff0c;可以在FIFO中禁用复位引脚。共有两种复位类型选项&#xff1a;异步复位和同步复位。…