×

Promise高级技巧,让您对Promise 的理解和使用更加熟练

作者:Terry2024.01.10来源:Web前端之家浏览:1532评论:0
关键词:PromiseAsyncAwait

Promise高级技巧,让您对Promise 的理解和使用更加熟练

JavaScript 项目中,利用 Promise 至关重要。令人惊讶的是,我观察到许多中级和经验丰富的前端开发人员,无论是同事还是面试官,都倾向于坚持传统做法,如“promiseInst.then()”、“promiseInst.catch()”和“Promise”。即使使用了“async/await”,有些人在使用它时也没有深入了解其细微差别。

然而,Promise 提供了大量巧妙且高级的用例,其中一些在 Alova 请求策略库中广泛使用。

Promise数组的串行执行

当面对必须按顺序执行一系列任务的场景时,最初的本能可能是使用“await”。然而,使用 Promise 的替代方法可能更优雅。

const requestAry = [() => api.request1(), () => api.request2(), () => api.request3()];
// Using `await`
for (const requestItem of requestAry) {
 await requestItem();
}
// Using promises for serial execution
const finallyPromise = requestAry.reduce(
 (currentPromise, nextRequest) => currentPromise.then(() => nextRequest()),
 Promise.resolve() // Initial promise for linking promises in the array
);

该方法使用“then”函数,可以简洁高效地连接 Promise,确保任务的串行执行。

在new Promise作用域外更改状态

假设你有多个页面的一些功能需要先收集用户的信息才能允许使用,在点击使用某功能前先弹出信息收集的弹框,你会怎么实现呢?

以下是不同水平的前端同学的实现思路:

初级前端:我写一个模态框,然后复制粘贴到其他页面,效率很杠杠的!

中级前端:你这不便于维护,我们要单独封装一下这个组件,在需要的页面引入使用!

高级前端:封什么装什么封!!!写在所有页面都能调用的地方,一个方法调用岂不更好?

看看高级前端怎么实现的,以vue3为例来看看下面的示例。

<!-- App.vue -->
<template>

  <!-- 以下是模态框组件 -->
  <div class="modal" v-show="visible">
    <div>
      用户姓名:<input v-model="info.name" />
    </div>
    <!-- 其他信息 -->
    <button @click="handleCancel">取消</button>
    <button @click="handleConfirm">提交</button>
  </div>

  <!-- 页面组件 -->
</template>

<script setup>
import { provide } from 'vue';

const visible = ref(false);
const info = reactive({
  name: ''
});
let resolveFn, rejectFn;

// 将信息收集函数函数传到下面
provide('getInfoByModal', () => {
  visible.value = true;
  return new Promise((resolve, reject) => {
    // 将两个函数赋值给外部,突破promise作用域
    resolveFn = resolve;
    rejectFn = reject;
  });
})

const handleConfirm = info => {
  resolveFn && resolveFn(info);
};
const handleCancel = () => {
  rejectFn && rejectFn(new Error('用户已取消'));
};
</script>

接下来直接调用getInfoByModal即可使用模态框,轻松获取用户填写的数据。

<template>
  <button @click="handleClick">填写信息</button>
</template>

<script setup>
import { inject } from 'vue';

const getInfoByModal = inject('getInfoByModal');
const handleClick = async () => {
  // 调用后将显示模态框,用户点击确认后会将promise改为fullfilled状态,从而拿到用户信息
  const info = await getInfoByModal();
  await api.submitInfo(info);
}
</script>

async/await的另类用法

很多人只知道在async函数调用时用await接收返回值,但不知道async函数其实就是一个返回promise的函数,例如下面两个函数是等价的:

js复制代码const fn1 = async () => 1;
const fn2 = () => Promise.resolve(1);

fn1(); // 也返回一个值为1的promise对象

而await在大部分情况下在后面接promise对象,并等待它成为fullfilled状态,因此下面的fn1函数等待也是等价的:

await fn1();

const promiseInst = fn1();
await promiseInst;

然而,await还有一个鲜为人知的秘密,当后面跟的是非promise对象的值时,它会将这个值使用promise对象包装,因此await后的代码一定是异步执行的。如下示例:

Promise.resolve().then(() => {
  console.log(1);
});
await 2;
console.log(2);
// 打印顺序位:1  2

等价于

Promise.resolve().then(() => {
  console.log(1);
});
Promise.resolve().then(() => {
  console.log(2);
})

您的支持是我们创作的动力!
温馨提示:本文作者系Terry ,经Web前端之家编辑修改或补充,转载请注明出处和本文链接:
https://jiangweishan.com/article/jsasync20240110.html

网友评论文明上网理性发言 已有0人参与

发表评论: