【前端教程】ES6 Promise 实战教程:从基础到游戏案例
前言
在 JavaScript 开发中,异步操作是非常常见的,比如定时器、网络请求等。而 Promise 作为 ES6 引入的异步编程解决方案,能够让我们更优雅地处理异步操作,避免\"回调地狱\"。
本文将通过一系列生动的实例(尤其是游戏场景),带你深入理解 Promise 的用法,包括 Promise.all()
、Promise.race()
以及 resolve
、reject
等核心概念。
异步和同步
在JavaScript和Vue开发中,同步(Synchronous)和异步(Asynchronous)是处理代码执行顺序的两种方式,它们的核心区别在于是否阻塞后续代码的执行:
1. 同步(Synchronous)
- 执行方式:代码按照顺序依次执行,前一段代码执行完毕后,才会执行下一段代码。
- 特点:会阻塞后续代码,直到当前操作完成。
- 适用场景:简单的计算、变量赋值、同步API调用等不需要等待的操作。
示例:
// 同步操作function syncOperation() { console.log(\"开始同步操作\"); // 模拟耗时操作(同步会阻塞) for (let i = 0; i < 1000000000; i++) { } console.log(\"同步操作完成\");}console.log(\"代码开始\");syncOperation();console.log(\"代码结束\"); // 必须等待同步操作完成后才执行
输出顺序:
代码开始开始同步操作同步操作完成代码结束
2. 异步(Asynchronous)
- 执行方式:代码不会等待当前操作完成,而是继续执行后续代码,当前操作完成后通过回调、Promise等方式通知结果。
- 特点:不会阻塞后续代码,提高程序执行效率,适合处理耗时操作。
- 适用场景:网络请求(API调用)、文件读写、定时器(
setTimeout
)等需要等待的操作。
示例(使用setTimeout
模拟异步):
// 异步操作function asyncOperation() { console.log(\"开始异步操作\"); // 模拟耗时操作(异步不会阻塞) setTimeout(() => { console.log(\"异步操作完成\"); }, 1000);}console.log(\"代码开始\");asyncOperation();console.log(\"代码结束\"); // 不需要等待异步操作完成
输出顺序:
代码开始开始异步操作代码结束// 1秒后...异步操作完成
3. 异步在Vue中的常见应用
在Vue组件中,异步操作非常常见,例如:
(1)网络请求(使用axios
)
export default { methods: { async fetchData() { console.log(\"开始请求数据\"); // 异步请求,不会阻塞后续代码 const response = await axios.get(\"https://api.example.com/data\"); console.log(\"数据请求完成\", response.data); } }, mounted() { this.fetchData(); console.log(\"组件挂载完成\"); // 先执行,不需要等待请求完成 }};
(2)定时器操作
export default { methods: { startTimer() { console.log(\"定时器开始\"); // 1秒后执行(异步) setTimeout(() => { console.log(\"定时器执行完毕\"); }, 1000); } }, created() { this.startTimer(); console.log(\"组件创建完成\"); // 先执行 }};
4. 同步与异步的核心区别
总结
- 同步:简单直接,但耗时操作会阻塞程序,导致界面卡顿。
- 异步:复杂但高效,适合处理需要等待的操作,避免程序阻塞。
在Vue开发中,处理网络请求、定时器等场景时,几乎都需要使用异步方式(如async/await
、Promise
),以保证用户体验的流畅性。
什么是 Promise?
Promise 是一种用于处理异步操作的对象,它代表了一个异步操作的最终完成(或失败)及其结果值。简单来说,Promise 就是用来管理异步代码的,让异步代码的执行顺序更加可控,代码结构更加清晰。
个人理解:当代码中出现了异步操作(setTimeout、ajax、setInterval),而且需要对这些操作的执行顺序进行控制时,就应该使用 Promise。Promise 能让代码看起来更\"优雅\"。
基础概念
- resolve:异步操作成功时调用的函数,将 Promise 状态改为成功
- reject:异步操作失败时调用的函数,将 Promise 状态改为失败
- then:用于指定 Promise 状态改变时的回调函数
- catch:用于捕获 Promise 执行过程中的错误
- Promise.all():等待所有 Promise 完成后再执行
- Promise.race():只要有一个 Promise 完成就执行(竞赛机制)
定时器小知识
setTimeout
:设定特定时间后执行一次函数setInterval
:每隔特定时间重复执行函数
实战案例
案例 1:游戏任务完成后升级(Promise.all())
在一个游戏中,有两个任务:采蘑菇和杀鸡。要求两个任务都完成以后才能升级。
<!DOCTYPE html><html><head> <meta charset=\"UTF-8\"> <title>游戏任务升级</title></head><body> <script> // 采蘑菇任务 function pickMushrooms() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log(\'采蘑菇任务完成\'); resolve(\'采蘑菇\'); // 传递任务结果 }, 2333); // 2.333秒完成 }); } // 杀鸡任务 function killChicken() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log(\'杀鸡任务完成\'); resolve(\'杀鸡\'); // 传递任务结果 }, 6666); // 6.666秒完成 }); } // 执行两个任务 let task1 = pickMushrooms(); let task2 = killChicken(); // 等待所有任务完成后升级 Promise.all([task1, task2]).then(function(results