文章目录
- 📋前言
- 🎯关于 promise(用于使用 JavaScript 编写的 Windows 应用商店应用)的内容分享
- 🧩promise 究竟是什么?承诺关系
- 🎯JavaScript Promise
- 🧩认识了解 Promise
- 🎯在 Vue3 项目中的实战应用
- 🧩运行效果
- 📝最后
📋前言
在前端编程中(甚至后端有时也是这样),我们在处理一些简短、快速的操作时,例如计算 1 + 1 的结果,往往在主线程中就可以完成。主线程作为一个线程,不能够同时接受多方面的请求。所以,当一个事件没有结束时,界面将无法处理其他请求。为了解决这个问题,JavaScript 中的异步操作函数往往通过回调函数来实现异步任务的结果处理。
这个时候 Promise 和异步编程就是一个很好的解决方法,接下来我们一起来了解学习下 Promise ,然后通过简单的应用来加深对 Promise 的印象。
🎯关于 promise(用于使用 JavaScript 编写的 Windows 应用商店应用)的内容分享
🔗详细内容地址:关于 promise(用于使用 JavaScript 编写的 Windows 应用商店应用)
当您使用 JavaScript 编写 Windows 应用商店应用时,一旦执行涉及异步 API 的操作时,就会遇到称为 promise 的构造。此外,无需很长时间,为顺序异步操作编写 promise 链就会成为您的一种习惯。
但是,在开发的过程中,您可能会遇到其他使用 promise 的情形,此时您可能无法完全了解具体情况。为 ListView 控件优化项目呈现功能就是一个很好的例子,如在 HTML ListView 优化性能示例中所示。我们将在随后的一篇博文中继续探究这一主题。或者,您也可以了解一下 Josh Williams 在 //build 2012 大会的深入探讨 WinJS 讨论(略有修改)中展示的以下重要代码段:
list.reduce(function callback (prev, item, i) {
var result = doOperationAsync(item);
return WinJS.Promise.join({ prev: prev, result: result}).then(function (v) {
console.log(i + ", item: " + item+ ", " + v.result);
});
})
该代码段将加入到 promise 来完成并行异步操作,并根据 list 中的命令按顺序提供结果。如果您一看到该代码就可以立即了解其功能,那么您完全可以跳过本博文!否则,让我们来仔细看一下 promise 的真正工作原理,以及其在 WinJS(Windows JavaScript 库)中的表达式,以便了解这些模式类型。
🧩promise 究竟是什么?承诺关系
首先,让我们来了解一下基本情况:promise 实际上无非就是一个代码构造或一个调用约定(如果您愿意)。因此,promise 与异步操作没有内在的关系,它们在这方面非常有用实属巧合!promise 只是一个对象,代表着可能会在将来某一时间可用(或现已可用)的值。这样,promise 的含义就像我们在人际关系中使用该术语一样。如果我说,“我承诺投递给您一打甜甜圈”,则很明显我无需即刻得到这些甜甜圈,而毫无疑问我假定自己可以在将来得到它们。一旦得到甜甜圈,我就会投递给您。
Promise 故暗示着两个代理方之间的关系:承诺发货的发货人与既是承诺的接受方又是收货人的消费者。发货人如何获得这些货物是其自己的事情。同样,消费者可以随意处理承诺和投递的货物。消费者甚至可与其他的消费者分享承诺。
在发货人和消费者之间,也存在着两个关系阶段,创建和履行。全部内容如下图所示。
通过该图中显示的流程,我们可以了解到分为两个阶段的关系是 promise 通过异步交货的方式得以履行的原因所在。这个过程的关键部分是一旦消费者认可请求 (即 promise),其可以继续生活 (异步),而不是等待 (同步)。这意味着消费者在等待承诺履行的同时可以做其他的事情,例如响应其他的请求,而这也是异步 API 的初衷。如果已得到货物,情况会怎样?此时,promise 将立即履行,就像是一种同步调用约定。
当然,对于这一关系,我们还要考虑一些额外的东西。在日常生活中,您一定作出过承诺,并且别人也对您作出过承诺。尽管许多承诺已经履行,但许多承诺无法兑现也是事实,例如快递员在为您送披萨的途中发生了交通事故!背弃的承诺是无法改变的事实,无论是在我们的个人生活还是异步编程方面,我们都必须接受。
在承诺关系中,这意味着发货人需要一种表达,“对不起,我无法兑现该承诺”的方式,而消费者也需要一种了解该事实的方式。其次,作为消费者,我们有时会对别人向我们作出的承诺失去耐心!因此,如果发货人可以在履行承诺的过程中跟踪进展情况,消费者也需要一种获得该信息的方式。第三,消费者还可以取消订单,并告知发货人其不再需要该货物。
将这些要求添加到图中之后,我们就会看到完整的关系:
🎯JavaScript Promise
Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。
由于 Promise 是 ES6 新增加的,所以一些旧的浏览器并不支持,苹果的 Safari 10 和 Windows 的 Edge 14 版本以上浏览器才开始支持 ES6 特性。以下是 Promise 浏览器支持的情况:
🧩认识了解 Promise
Promise 是 JavaScript 中用于处理异步操作的对象,它代表了一个异步操作的最终完成或失败,并可以返回结果或错误信息。
Promise 对象有三个状态:
1. Pending(进行中):初始状态,表示异步操作尚未完成或失败。
2. Fulfilled(已完成):表示异步操作成功完成,并返回了结果。
3. Rejected(已失败):表示异步操作遇到了错误或失败。
创建 Promise 对象时,需要传入一个执行器函数,该函数接受两个参数 resolve 和 reject。在执行器函数中,通过调用 resolve 函数来将 Promise 状态从 Pending 转变为 Fulfilled ,或者通过调用 reject 函数将其转变为 Rejected 。例如:
const promise = new Promise((resolve, reject) => {
// 异步操作
if (/* 异步操作成功 */) {
resolve(result); // 将状态设置为 Fulfilled,并返回结果
} else {
reject(error); // 将状态设置为 Rejected,并返回错误信息
}
});
Promise 提供了链式调用的方法,例如 then 、catch 和 finally。通过这些方法,可以在 Promise 完成或失败后执行相应的操作。then 方法接收两个回调函数作为参数,第一个回调函数在 Promise 被 Fulfilled 时执行,接收成功的结果作为参数;第二个回调函数在 Promise 被 Rejected 时执行,接收错误信息作为参数。catch 方法用于捕获发生的错误,而 finally 方法则在 Promise 完成后无论成功或失败都会执行。例如:
promise
.then((result) => {
// 处理成功的结果
})
.catch((error) => {
// 处理错误信息
})
.finally(() => {
// 执行清理操作
});
下面可以通过这张图看一下 Promise 的执行过程。
Promise 还提供了一些静态方法,如 Promise.all 、Promise.race 等。Promise.all 接收一个 Promise 数组作为参数,并返回一个新的 Promise ,只有当所有的 Promise 都成功完成时,这个新的 Promise 才会成功完成,返回结果数组。而 Promise.race 则接收一个 Promise 数组作为参数,并返回一个新的 Promise ,只要其中任何一个 Promise 完成(无论成功还是失败),这个新的 Promise 就会完成。
🎯在 Vue3 项目中的实战应用
通过上面的内容学习和了解,我们大致搞清楚了什么是 Promise ,接下来我们学以致用,在 Vue3 项目中使用 Promise 做一个示例。
创建一个 Vue 组件,名字叫 AsyncComponent.vue。
<template>
<div>
<button @click="startAsyncTask">开始异步任务</button>
<p v-if="loading">正在加载中...</p>
<p v-else-if="result">异步任务结果:{{ result }}</p>
<p v-else>点击按钮开始异步任务</p>
</div>
</template>
<script setup>
import { ref } from "vue";
const loading = ref(false); // 是否正在加载
const result = ref(null); // 异步任务结果
const startAsyncTask = () => {
loading.value = true; // 设置加载状态为true
// 使用Promise包装异步任务
const asyncTask = new Promise((resolve, reject) => {
// 模拟异步任务,这里可以是一个API请求、定时器等异步操作
setTimeout(() => {
const randomNum = Math.random();
if (randomNum > 0.5) {
resolve(`成功,随机数:${randomNum}`);
} else {
reject(new Error(`失败,随机数:${randomNum}`));
}
}, 2000);
});
asyncTask
.then((res) => {
result.value = res; // 更新异步任务结果
})
.catch((error) => {
console.error(error); // 处理异步任务失败的情况
})
.finally(() => {
loading.value = false; // 无论成功或失败都将加载状态设置为false
});
};
</script>
在需要使用异步组件的父组件中引入并使用 AsyncComponent 组件。在这个项目中,我们在 ElementTest2.vue 这个页面引入了 AsyncComponent 组件。
<template>
<div>
<h1>异步组件示例</h1>
<AsyncComponent />
</div>
</template>
<script>
import AsyncComponent from "./AsyncComponent.vue";
export default {
components: {
AsyncComponent,
},
};
</script>
🧩运行效果
界面如下。
点击按钮后,进入加载状态
成功时返回结果如下。
失败时返回结果如下。
界面中的 result 之所以没改变,是因为上一次加载成功时把结果赋值给 result 了,但是加载失败的话不会赋值给 result ,而是直接输出到控制台。
📝最后
到此,这就是文章的全部的内容了。通过这篇文章,我们可以快速了解学习什么是 Promise ,然后通过实战应用学会使用 Promise ,通过使用 Promise ,我们可以更好地管理和组织异步操作,避免了回调地狱,使得代码更具有可读性、可维护性和可扩展性。