首页 > 编程语言 >JavaScript 异步编程入门

JavaScript 异步编程入门

时间:2024-10-12 20:48:59浏览次数:7  
标签:异步 编程 console JavaScript Promise async data

最近开始不断学习实践 JavaScript ,出于性能测试的敏感,首先研究了 JavaScript 的异步编程实践,目前看跟之前学过的 Java 和 Go 都不太一样。使用的语法上相对更加复杂,也可能因为我实践得还太少。

异步编程

异步编程是一种在程序执行过程中,不阻塞主线程的任务处理方式。相较于同步编程,异步编程允许程序在等待某个任务(例如网络请求或文件读写)完成的同时,继续执行其他操作。这种方式极大提高了程序的效率,尤其在处理大量 I/O 操作时,表现尤为突出。

在 JavaScript 中,异步编程尤为重要,原因在于它的单线程特性。JavaScript 在浏览器环境下运行时,只有一个主线程负责执行代码。如果程序中某个任务需要较长时间才能完成(比如网络请求、数据库查询等),而没有采用异步处理方式,主线程将会被阻塞,导致整个页面的交互变得迟缓甚至无响应。

为了避免这种情况,JavaScript 提供了多种异步处理方式,如回调函数Promiseasync/await等。通过这些机制,JavaScript 能够在处理耗时任务时,不阻塞主线程,保持页面的流畅性和响应性。

回调函数(Callback)

回调函数是指作为参数传递给另一个函数,并在该函数执行完毕后调用的函数。在 JavaScript 的异步编程中,回调函数是最早且最基础的实现方式之一。当某个异步操作(如网络请求或定时器)完成时,JavaScript 运行时环境会调用提供的回调函数,继续执行后续的逻辑。这种模式允许我们在异步任务完成后进行处理,而不阻塞主线程。

在 JavaScript 中,回调函数通过结合浏览器或 Node.js 的事件循环机制来实现异步行为。单单使用 JavaScript 本身无法实现异步,而是通过将任务交给浏览器或 Node.js 的运行时(如定时器、I/O 操作、网络请求等)来处理,等这些任务完成后,再通过回调函数把结果传回给 JavaScript 主线程继续执行。这整个过程就是实现异步的关键。

示例
function fetchData(callback) {  
    console.log("Fetching data...");  
    setTimeout(() => {// 模拟耗时操作  
        // 模拟耗时操作  
        const data = "Hello FunTester!";  
        callback(data); // 调用回调函数,传递数据  
    }, 1000);  
}  
  
function processData(data) {  
    console.log("Data received:", data);// 处理数据的逻辑  
}  
  
console.info("start --------");  
fetchData(processData);// 调用 fetchData 函数,传入回调函数  
console.info("end --------");

在这个例子中,fetchData 模拟了一个异步数据获取的操作,执行完成后调用回调函数 processData 来处理获取到的数据。控制台打印:

start --------
Fetching data...
end --------
Data received: Hello FunTester!

Promise

Promise 是一种用于处理异步操作的对象,它代表了一个异步操作的最终完成(或失败)及其结果值。Promise 提供了更清晰、更可读的方式来管理多个异步操作,特别是当它们相互依赖时。相比回调函数,Promise 能避免回调地狱,使代码结构更加扁平化和易于维护。

Promise 的三种状态

  1. Pending(待定):初始状态,表示异步操作尚未完成,也没有结果。
  2. Fulfilled(已完成):异步操作成功完成,并返回一个值。
  3. Rejected(已拒绝):异步操作失败,并返回一个原因。

在 Promise 的生命周期中,它只能从 pending 状态转移到 fulfilledrejected 状态,并且一旦状态发生变化,结果就不会再改变。

Promise 的基本用法

一个 Promise 对象会接受一个函数作为参数,该函数本身又有两个参数:resolvereject。当异步操作成功时,调用 resolve 来将 Promise 状态改为 fulfilled;当操作失败时,调用 reject 将状态改为 rejected

.then().catch() 的用法

  • .then():用于处理 Promise 成功完成(fulfilled)后的结果。你可以在 .then() 中执行后续操作,链式调用。
  • .catch():用于捕获 Promise 的错误(rejected),并处理异常情况。

Promise 示例

const fetchData = async () => {  
    return new Promise((resolve, reject) => {  
        setTimeout(() => {  
            const success = true; // 模拟成功或失败  
            if (success) {// 成功, 调用 resolve, 并传递数据  
                resolve("hello, FunTester");  
            } else {// 失败, 调用 reject, 并传递错误信息  
                reject("sorry, error occurred");  
            }  
        });  
    });  
};  
  
console.info("start--------------");  
// 使用 Promise 来处理异步操作  
fetchData()  
    .then((data) => {// 成功时的处理  
        console.log("received:", data);  
        return data.length;  
    })  
    .then((age) => {// 成功时的处理  
        console.log("length:", age);  
    })  
    .catch((error) => {// 失败时的处理  
        console.error("Error:", error);  
    });  
  
console.info("end--------------");

控制台打印:

start--------------
end--------------
received: hello, FunTester
length: 16

下面是一些小小的 tips:

  • Promise 提供了一种更加简洁、优雅的方式来处理异步操作,避免回调地狱。
  • 它有三种状态:pending(待定)、fulfilled(已完成)、rejected(已拒绝)。
  • 使用 .then() 处理成功结果,使用 .catch() 捕获和处理错误。
  • 多个异步操作可以链式调用,提升了代码的可读性和维护性。

async/await

async/await 是 ES2017(ES8)引入的语法,提供了一种更加简洁的方式来处理异步代码,使其看起来更像同步代码。这种方式可以减少 Promise 链的复杂性,提升代码的可读性和维护性。async/await 实际上是基于 Promises 之上的语法糖。

通过使用 asyncawait,我们可以编写看起来像同步执行的代码,但它在内部仍然是异步的。这种写法可以避免 Promise 链式调用的繁琐结构,将异步任务的执行流顺序化,逻辑更加清晰。

async/await 的基本用法

  1. async 函数:声明一个 async 函数,它会自动返回一个 Promise。即使没有显式返回 Promise,async 函数默认会把返回值封装成一个 Promise。
  2. await 表达式:用于等待一个 Promise 的结果。它暂停 async 函数的执行,直到 Promise 解决(resolve)或拒绝(reject),然后继续执行后续代码。

示例:使用 async/await

const fetchData = () => {  
    return new Promise((resolve, reject) => {  
        setTimeout(() => {// 模拟异步操作  
            const success = true;  
            if (success) {  
                resolve("hello funtester");  
            } else {  
                reject("sorry, error");  
            }  
        }, 1000);  
    });  
};  
  
async function getData() {  
    try {  
        const data = await fetchData(); // 等待 Promise 解决  
        console.log("Data received:", data);  
    } catch (error) {  
        console.error("Error:", error); // 处理错误  
    }  
}  
console.info("start----------------");  
let data = getData();  
console.log("data:", data);  
console.info("end----------------");

控制台打印:

start----------------
data: Promise { <pending> }
end----------------
Data received: hello funtester

在使用 async/await 时,错误处理的方式类似于同步代码中捕获异常。我们可以使用 try/catch 块来处理异步操作中的异常,这种方式比在每个 .then() 末尾添加 .catch() 更加直观。

async/await 基于 Promise

需要注意的是,async/await 并不是替代 Promise 的机制,而是基于 Promise 进行的更高级抽象。它们简化了 Promise 的链式调用,消除了嵌套结构。可以把 await 视作一个暂停点,等待 Promise 完成(无论是成功还是失败),使得异步代码的处理更符合程序的执行逻辑。

异步编程的重要性

在 JavaScript 中,异步编程至关重要,因为 JavaScript 运行在单线程环境中,尤其是在浏览器和 Node.js 等平台中。单线程意味着同一时间只能执行一个任务。如果代码中的某些操作(如网络请求、文件读取或定时任务)需要较长的执行时间,而 JavaScript 只支持同步编程的话,整个线程将被阻塞,用户界面会变得卡顿或无响应。因此,异步编程通过不阻塞主线程来解决这个问题,使得 JavaScript 能够高效处理 I/O 密集型任务,保持应用的流畅运行。

当然 JavaScript 异步编程的内容还有其他高级用法,比如学习 Promise.all、Promise.race 等,将来等我实践充足再来分享。

标签:异步,编程,console,JavaScript,Promise,async,data
From: https://blog.51cto.com/FunTester/12232157

相关文章

  • 【JavaScript】LeetCode:61-65
    文章目录61课程表62实现Trie(前缀树)63全排列64子集65电话号码的字母组合61课程表Map+BFS拓扑排序:将有向无环图转为线性顺序。遍历prerequisites:1.数组记录每个节点的入度,2.哈希表记录依赖关系。n=6,prerequisites=[[3,0],[3,1],[4,1],[4,2],[5,3],[5,4]]。0、1......
  • 实验一 现代C++编程初体验
    case1://现代C++标准库、算法库体验//本例用到以下内容://1.字符串string,动态数组容器类vector、迭代器//2.算法库:反转元素次序、旋转元素//3.函数模板、const引用作为形参#include<iostream>#include<string>#include<vector>#include<algorithm>usi......
  • 实验1 现代C++编程初体验
    实验1现代C++编程初体验 task1:1//现代C++标准库、算法库体验2//本例用到以下内容:3//1.字符串string,动态数组容器类vector、迭代器4//2.算法库:反转元素次序、旋转元素5//3.函数模板、const引用作为形参6#include<iostream>7#include<strin......
  • 实验1 现代C++基础编程
    task1实验代码:#include<iostream>#include<string>#include<vector>#include<algorithm>usingnamespacestd;//声明//模板函数声明template<typenameT>voidoutput(constT&c);//普通函数声明voidtest1();voidtest2();voidtest3......
  • 实验1现代c++编程初体验
    test1:源代码:1#include<iostream>2#include<string>3#include<vector>4#include<algorithm>5usingnamespacestd;6template<typenameT>7voidoutput(constT&c);8voidtest1();9voidtest2();10voidtest3......
  • 实验1 现代C++编程初体验
    task1://现代C++标准库、算法库体验//本例用到以下内容://1.字符串string,动态数组容器类vector、迭代器//2.算法库:反转元素次序、旋转元素//3.函数模板、const引用作为形参#include<iostream>#include<string>#include<vector>#include<algorithm>usin......
  • 前后端分离nodejs_vue+javascript个人身体健康档案管理系统
    目录技术栈具体实现截图开发工具和技术简介错误处理和异常处理nodejs类核心代码部分展示解决的思路其他题目推荐源码获取/联系我技术栈该系统将采用B/S结构模式,开发软件有很多种可以用,本次开发用到的软件是vscode,用到的数据库是MySQL,为了更加便捷地使用数据库,用到了......
  • JavaScript原型链污染漏洞分析
    原型链污染漏洞CVE:1、yargs-Parser输入验证错误漏洞(CVE-2020-7608)2、tough-cookie安全漏洞(CVE-2023-26136)3、JSON5原型污染漏洞(CVE-2022-46175) 漏洞描述:1、yargs-Parser输入验证错误漏洞(CVE-2020-7608):yargs-parser是一款选项解析器。yargs-parser13.1.2之前......
  • JavaScript
    什么是JavaScript?Web标准也称为网页标准,由一系列的标准组成,大部分由W3C(WorldWideWebConsortium,万维网联盟)负责制定。三个组成部分:HTML:负责网页的基本结构(页面元素和内容)。CSS:负责网页的表现效果(页面元素的外观、位置等页面样式,如:颜色、大小等)。JavaScript:负责网页的......
  • 大学生HTML期末大作业——HTML+CSS+JavaScript购物商城(篮球)
    HTML+CSS+JS【购物商城】网页设计期末课程大作业web前端开发技术web课程设计网页规划与设计......