8 个关于 Promise 高级用途的技巧

<pre style="outline: 0px;font-family: monospace, monospace;font-size: 16px;text-align: left;color: rgb(63, 63, 63);letter-spacing: 0.544px;background-color: rgb(255, 255, 255);word-spacing: 0.8px;visibility: visible;">我发现很多人只知道如何常规地使用promise。</pre>

在js项目中,promise的使用应该是必不可少的,但我发现在同事和面试官中,很多中级以上的前端仍然坚持promiseInst.then()、promiseInst.catch()、Promise等常规用法等等。即使是 async/await 他们也只知道它但不知道为什么要使用它。

但实际上,Promise 有很多巧妙的高级用法,并且一些高级用法在 alova 请求策略库内部也被广泛使用。

现在,我将与大家分享8个高级使用技巧。希望这些技巧能够对你有所帮助,现在,我们就开始吧。

1. Promise数组的串行执行

例如,如果你有一组接口需要串行执行,你可能首先想到使用await。

const requestAry = [() => api.request1(), () => api.request2(), () => api.request3()];

如果使用promise,可以使用then函数串联多个promise,实现串行执行。

const requestAry = [() => api.request1(), () => api.request2(), () => api.request3()];

2. 在新的 Promise 范围之外更改状态

假设你有多个页面,其功能要求在允许使用之前收集用户信息。点击使用某个功能之前,会弹出一个弹框进行信息收集。你会如何实施这个?

以下是不同级别前端同学的实现思路:

初级前端:我写一个模态框,然后复制粘贴到其他页面。效率非常高!

中级前端:这个不好维护。我们需要单独封装这个组件,并在需要的页面引入!

高级前端:安装任何密封的东西!!!把方法调用写在所有页面都可以调用的地方不是更好吗?

想要了解高级前端是如何实现的,以vue3为例,看一下下面的例子。

<!-- App.vue -->

接下来,getInfoByModal就可以通过直接调用模态框来轻松获取用户填写的数据。

<template>

这也是很多UI组件库中封装常用组件的一种方式。

3. async/await 的替代用法

很多人只知道它是用来在调用await时接收async函数的返回值的,却不知道async函数它实际上是一个返回promise的函数。例如,以下两个函数是等效的:

const fn1 = async () => 1;

在大多数情况下,await 会跟随 Promise 对象并等待它完全填充。因此,下面的 fn1 函数 wait 也是等价的:

await fn1();

然而,await也有一个鲜为人知的秘密。当它后面跟的值不是promise对象时,它会用promise对象包装该值,所以await后面的代码必须异步执行。例子:

Promise.resolve().then(() => {

相当于

Promise.resolve().then(() => {

4. 承诺实施请求共享

当一个请求已经发出但尚未得到响应时,再次发出相同的请求,就会造成请求的浪费。此时,我们可以将第一个请求的响应与第二个请求共享。

request('GET', '/test-api').then(response1 => {

上述两个请求实际上只发送一次,同时收到相同的响应值。

那么,请求共享有哪些使用场景呢?我认为有以下三个:

  • 当页面渲染多个内部组件同时获取数据时;

  • 提交按钮未禁用且用户连续多次点击提交按钮;

  • 预加载数据的情况下,预加载完成之前进入预加载页面;

这也是alova的高级功能之一。要实现请求共享,需要使用promise的缓存功能,即一个promise对象可以通过多次await获取数据。简单的实现思路如下:

const pendingPromises = {};

上述两个请求实际上只发送一次,同时收到相同的响应值。

那么,请求共享有哪些使用场景呢?我认为有以下三个:

  • 当页面渲染多个内部组件同时获取数据时;

  • 提交按钮未禁用且用户连续多次点击提交按钮;

  • 预加载数据的情况下,预加载完成之前进入预加载页面;

这也是alova的高级功能之一。要实现请求共享,需要使用promise的缓存功能,即一个promise对象可以通过多次await获取数据。简单的实现思路如下:

const promise = new Promise((resolve, reject) => {

正确答案是已满状态。我们只需要记住,一旦待处理的promise从一种状态转移到另一种状态,就无法更改。因此,例子中是先转为fulfilled状态,然后reject()就不会再转为rejected状态。

6.彻底明确then/catch/finally返回值

一句话概括就是,上面三个函数都会返回一个新的promise包装对象。包装后的值是执行回调函数的返回值。如果回调函数抛出错误,它将包装拒绝状态承诺。似乎不太容易理解,我们来看一个例子:

我们可以将它们一一复制到浏览器控制台并运行它们以帮助理解。

// then function

7、then函数的第二次回调和catch回调有什么区别?

当请求发生错误时,会触发 Promise 的 then 的第二个回调函数和 catch。乍一看没有区别,但实际上前者无法捕获then当前第一个回调函数中抛出的错误,但catch可以。

Promise.resolve().then(

原理就如上一点所说的。catch 函数是在 then 函数返回的处于拒绝状态的 Promise 上调用的,因此它的错误自然可以被捕获。

8.(最终)Promise实现koa2洋葱中间件模型

koa2框架引入了洋葱模型,可以让你的请求像剥洋葱一样一层层进去,再一层层出来,从而实现请求前后处理的统一。

image.png

我们来看一个简单的 koa2 洋葱模型:

const app = new Koa();

上面的输出是a-start -> b-start -> b-end -> a-end,这样神奇的输出序列是如何实现的呢?有人没天赋,简单的用20行左右的代码就实现了。如有雷同,纯属巧合。

接下来我们分析一下

注:以下内容对新手不友好,请谨慎阅读。

首先先保存中间件函数,在listen函数中收到请求后调用洋葱模型执行。

function action(koaInstance, ctx) {

收到请求后,从第一个中间件开始串行执行next之前的前置逻辑。

//Start to start middleware call

处理next之后的post逻辑

function action(koaInstance, ctx) {

至此,一个简单的洋葱模型就已经实现了。

总结

以上就是我今天想与你分享的8个关于Promise的高级用途的全部内容,如果你觉得有用的话,请记得点赞我,关注我,并将这个内容分享给你的小伙伴们,也许能够帮助到他。

最后,感谢你的阅读,祝编程愉快!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,233评论 6 495
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,357评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,831评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,313评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,417评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,470评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,482评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,265评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,708评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,997评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,176评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,503评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,150评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,391评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,034评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,063评论 2 352

推荐阅读更多精彩内容