国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

八個關于 Promise 的高級用途的技巧

開發 前端
在js項目中,promise的使用應該是必不可少的,但我發現在同事和面試官中,很多中級以上的前端仍然堅持promiseInst.then()、promiseInst.catch()、Promise等常規用法等等。即使是 async/await 他們也只知道它但不知道為什么要使用它。

我發現很多人只知道如何常規地使用promise。

在js項目中,promise的使用應該是必不可少的,但我發現在同事和面試官中,很多中級以上的前端仍然堅持promiseInst.then()、promiseInst.catch()、Promise等常規用法等等。即使是 async/await 他們也只知道它但不知道為什么要使用它。

但實際上,Promise 有很多巧妙的高級用法,并且一些高級用法在 alova 請求策略庫內部也被廣泛使用。

現在,我將與大家分享8個高級使用技巧。希望這些技巧能夠對你有所幫助,現在,我們就開始吧。

1. Promise數組的串行執行

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

const requestAry = [() => api.request1(), () => api.request2(), () => api.request3()];
for (const requestItem of requestAry) {
  await requestItem();
}

如果使用promise,可以使用then函數串聯多個promise,實現串行執行。

const requestAry = [() => api.request1(), () => api.request2(), () => api.request3()];
const finallyPromise = requestAry.reduce(
     (currentPromise, nextRequest) => currentPromise.then(() => nextRequest()),
     Promise.resolve() // Create an initial promise for linking promises in the array
);

2. 在新的 Promise 范圍之外更改狀態

假設你有多個頁面,其功能要求在允許使用之前收集用戶信息。 點擊使用某個功能之前,會彈出一個彈框進行信息收集。 你會如何實施這個?

以下是不同級別前端同學的實現思路:

初級前端:我寫一個模態框,然后復制粘貼到其他頁面。 效率非常高!

中級前端:這個不好維護。 我們需要單獨封裝這個組件,并在需要的頁面引入!

高級前端:安裝任何密封的東西! ! ! 把方法調用寫在所有頁面都可以調用的地方不是更好嗎?

想要了解高級前端是如何實現的,以vue3為例,看一下下面的例子。

<!-- App.vue -->
<template>
<!-- The following is the modal box component -->
   <div class="modal" v-show="visible">
     <div>
       User name: <input v-model="info.name" />
     </div>
     <!-- Other information -->
     <button @click="handleCancel">Cancel</button>
     <button @click="handleConfirm">Submit</button>
   </div>
   <!-- Page components -->
</template>
<script setup>
import { provide } from 'vue';
const visible = ref(false);
const info = reactive({
   name: ''
});
let resolveFn, rejectFn;
// Pass the information collection function to the following
provide('getInfoByModal', () => {
   visible.value = true;
   return new Promise((resolve, reject) => {
     // Assign the two functions to the outside and break through the promise scope
     resolveFn = resolve;
     rejectFn = reject;
   });
})
const handleConfirm = () => {
   resolveFn && resolveFn(info);
};
const handleCancel = () => {
   rejectFn && rejectFn(new Error('User has canceled'));
};
</script>

接下來,getInfoByModal就可以通過直接調用模態框來輕松獲取用戶填寫的數據。

<template>
   <button @click="handleClick">Fill in the information</button>
</template>


<script setup>
import { inject } from 'vue';
const getInfoByModal = inject('getInfoByModal');
const handleClick = async () => {
   // After the call, the modal box will be displayed. After the user clicks to confirm, the promise will be changed to the fullfilled state to obtain the user information.
   const info = await getInfoByModal();
   await api.submitInfo(info);
}
</script>

這也是很多UI組件庫中封裝常用組件的一種方式。

3. async/await 的替代用法

很多人只知道它是用來在調用await時接收async函數的返回值的,卻不知道async函數它實際上是一個返回promise的函數。 例如,以下兩個函數是等效的:

const fn1 = async () => 1;
const fn2 = () => Promise.resolve(1);


fn1(); // Also returns a promise object with a value of 1

在大多數情況下,await 會跟隨 Promise 對象并等待它完全填充。 因此,下面的 fn1 函數 wait 也是等價的:

await fn1();


const promiseInst = fn1();
await promiseInst;

然而,await也有一個鮮為人知的秘密。 當它后面跟的值不是promise對象時,它會用promise對象包裝該值,所以await后面的代碼必須異步執行。 例子:

Promise.resolve().then(() => {
  console.log(1);
});
await 2;
console.log(2);
//Print order bits: 1 2

相當于

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

4. 承諾實施請求共享

當一個請求已經發出但尚未得到響應時,再次發出相同的請求,就會造成請求的浪費。 此時,我們可以將第一個請求的響應與第二個請求共享。

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

上述兩個請求實際上只發送一次,同時收到相同的響應值。

那么,請求共享有哪些使用場景呢? 我認為有以下三個:

  • 當頁面渲染多個內部組件同時獲取數據時;
  • 提交按鈕未禁用且用戶連續多次點擊提交按鈕;
  • 預加載數據的情況下,預加載完成之前進入預加載頁面;

這也是alova的高級功能之一。 要實現請求共享,需要使用promise的緩存功能,即一個promise對象可以通過多次await獲取數據。 簡單的實現思路如下:

const pendingPromises = {};
function request(type, url, data) {
   // Use the request information as the only request key to cache the promise object being requested
   //Requests with the same key will reuse promise
   const requestKey = JSON.stringify([type, url, data]);
   if (pendingPromises[requestKey]) {
     return pendingPromises[requestKey];
   }
   const fetchPromise = fetch(url, {
     method: type,
     data: JSON.stringify(data)
   })
   .then(response => response.json())
   .finally(() => {
     delete pendingPromises[requestKey];
   });
   return pendingPromises[requestKey] = fetchPromise;
}

上述兩個請求實際上只發送一次,同時收到相同的響應值。

那么,請求共享有哪些使用場景呢? 我認為有以下三個:

  • 當頁面渲染多個內部組件同時獲取數據時;
  • 提交按鈕未禁用且用戶連續多次點擊提交按鈕;
  • 預加載數據的情況下,預加載完成之前進入預加載頁面;

這也是alova的高級功能之一。 要實現請求共享,需要使用promise的緩存功能,即一個promise對象可以通過多次await獲取數據。 簡單的實現思路如下:

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

正確答案是已滿狀態。 我們只需要記住,一旦待處理的promise從一種狀態轉移到另一種狀態,就無法更改。 因此,例子中是先轉為fulfilled狀態,然后reject()就不會再轉為rejected狀態。

6.徹底明確then/catch/finally返回值

一句話概括就是,上面三個函數都會返回一個新的promise包裝對象。 包裝后的值是執行回調函數的返回值。 如果回調函數拋出錯誤,它將包裝拒絕狀態承諾。 似乎不太容易理解,我們來看一個例子:

我們可以將它們一一復制到瀏覽器控制臺并運行它們以幫助理解。

// then function
Promise.resolve().then(() => 1); // The return value is new Promise(resolve => resolve(1))
Promise.resolve().then(() => Promise.resolve(2)); // Return new Promise(resolve => resolve(Promise.resolve(2)))
Promise.resolve().then(() => {
   throw new Error('abc')
}); // Return new Promise(resolve => resolve(Promise.reject(new Error('abc'))))
Promise.reject().then(() => 1, () => 2); // The return value is new Promise(resolve => resolve(2))


//catch function
Promise.reject().catch(() => 3); // The return value is new Promise(resolve => resolve(3))
Promise.resolve().catch(() => 4); // The return value is new Promise(resolve => resolve(promise object that calls catch))
//When the finally function returns a non-promise value, return the promise object before the finally function.
Promise.resolve().finally(() => {}); // Return Promise.resolve()
Promise.reject().finally(() => {}); // Return Promise.reject()
// When the return value of the finally function is promise, wait for the returned promise to be parsed before returning the promise object before the finally function.
Promise.resolve(5).finally(() => new Promise(res => {
   setTimeout(res, 1000);
})); // Return the Promise in pending status, which will be resolved to 5 after 1 second.
Promise.reject(6).finally(() => new Promise(res => {
   setTimeout(res, 1000);
})); // Return the Promise in the pending state, and throw the number 6 after 1 second

7、then函數的第二次回調和catch回調有什么區別?

當請求發生錯誤時,會觸發 Promise 的 then 的第二個回調函數和 catch。 乍一看沒有區別,但實際上前者無法捕獲then當前第一個回調函數中拋出的錯誤,但catch可以。

Promise.resolve().then(
   () => {
     throw new Error('Error from success callback');
   },
   () => {
     // will not be executed
   }
).catch(reason => {
   console.log(reason.message); // Will print out "error from success callback"
});

原理就如上一點所說的。 catch 函數是在 then 函數返回的處于拒絕狀態的 Promise 上調用的,因此它的錯誤自然可以被捕獲。

8.(最終)Promise實現koa2洋蔥中間件模型

koa2框架引入了洋蔥模型,可以讓你的請求像剝洋蔥一樣一層層進去,再一層層出來,從而實現請求前后處理的統一。

我們來看一個簡單的 koa2 洋蔥模型:

const app = new Koa();
app.use(async (ctx, next) => {
  console.log('a-start');
  await next();
  console.log('a-end');
});
app.use(async (ctx, next) => {
  console.log('b-start');
  await next();
  console.log('b-end');
});


app.listen(3000);

上面的輸出是a-start -> b-start -> b-end -> a-end,這樣神奇的輸出序列是如何實現的呢? 有人沒天賦,簡單的用20行左右的代碼就實現了。 如有雷同,純屬巧合。

接下來我們分析一下

注:以下內容對新手不友好,請謹慎閱讀。

首先先保存中間件函數,在listen函數中收到請求后調用洋蔥模型執行。

function action(koaInstance, ctx) {
  // ...
}


class Koa {
   middlewares = [];
   use(mid) {
     this.middlewares.push(mid);
   }
   listen(port) {
     // Pseudocode simulates receiving request
     http.on('request', ctx => {
       action(this, ctx);
     });
   }
}

收到請求后,從第一個中間件開始串行執行next之前的前置邏輯。

//Start to start middleware call
function action(koaInstance, ctx) {
   let nextMiddlewareIndex = 1; // Identifies the next middleware index to be executed


   //Define next function
   function next() {
     // Before peeling the onion, calling next will call the next middleware function
     const nextMiddleware = middlewares[nextMiddlewareIndex];
     if (nextMiddleware) {
       nextMiddlewareIndex++;
       nextMiddleware(ctx, next);
     }
   }
   //Start execution from the first middleware function and pass in the ctx and next functions
   middlewares[0](ctx, next);
}

處理next之后的post邏輯

function action(koaInstance, ctx) {
   let nextMiddlewareIndex = 1;
   function next() {
     const nextMiddleware = middlewares[nextMiddlewareIndex];
     if (nextMiddleware) {
       nextMiddlewareIndex++;
       // A return is also added here to allow the execution of the middleware function to be executed in series from back to front using promises (it is recommended to understand this return repeatedly)
       return Promise.resolve(nextMiddleware(ctx, next));
     } else {
       // When the pre-logic of the last middleware is executed, return the fullyfilled promise and start executing the post-logic after next.
       return Promise.resolve();
     }
   }
   middlewares[0](ctx, next);
}

至此,一個簡單的洋蔥模型就已經實現了。

總結

以上就是我今天想與你分享的8個關于Promise的高級用途的全部內容,如果你覺得有用的話,請記得點贊我,關注我,并將這個內容分享給你的小伙伴們,也許能夠幫助到他。

責任編輯:華軒 來源: web前端開發
相關推薦

2025-02-07 15:01:49

Promise數組前端

2024-03-06 13:56:00

項目awaitpromise

2024-07-02 09:03:48

2012-10-29 11:01:17

2025-02-10 10:38:24

2022-12-15 16:38:17

2022-05-30 00:04:16

開源Github技巧

2023-10-24 09:25:23

IT技巧文化

2010-08-25 11:14:05

云安全數據安全網絡安全

2025-01-02 15:08:36

SpringBoot自動配置Java

2023-06-27 09:21:33

2025-05-09 09:26:12

2023-01-03 11:47:47

2023-02-22 14:50:59

技術AI

2024-04-01 07:51:49

Exclude?工具類型TypeScript

2024-03-21 09:58:27

ExtractTypeScript工具類型

2021-11-19 10:40:14

物聯網物聯網安全IoT

2021-01-11 08:30:02

Dubbo服務

2023-09-04 15:48:05

JavaScript語言

2024-06-27 10:45:27

點贊
收藏

51CTO技術棧公眾號

亚洲国产欧美一区二区三区同亚洲| 国产一区二区不卡视频在线观看| 黑丝一区二区| 毛片在线播放网站| 欧美一级高清大全免费观看| 国产成人午夜| 亚洲性xxxx| 久久久不卡网国产精品二区| 在线看的你懂得| 日韩视频在线永久播放| 日本免费看黄色| 天天影视涩香欲综合网| 免费观看的av网站| 一区二区三区精品| 国产在线导航| 亚洲精品少妇30p| 国产精品一区二区在线观看| 久久久精品区| 欧美色欧美亚洲另类七区| 色94色欧美sute亚洲线路一ni | yiren22亚洲综合| caoporn国产一区二区| 丁香影院在线| 全部孕妇毛片丰满孕妇孕| 亚洲aⅴ男人的天堂在线观看| 精品国产网站在线观看| 亚洲最新视频在线播放| 2024国产精品视频| 日韩电影免费一区| 日韩精品欧美激情一区二区| 精品一区二区三区在线观看视频 | 成人av电影观看| 韩国版免费三体| 色综合小说天天综合网| 亚洲精品偷拍视频| 免费精品视频一区二区三区| 国产精品wwww| 国产www精品| 久久久免费精品视频| 蜜臀久久精品| 九色在线视频蝌蚪| 一级片免费在线| 黄色av观看| 人人澡人人爽| www.成人精品免费网站青椒| 天天碰免费视频| 日韩黄色片视频| 日韩中文字幕组| 欧美色18zzzzxxxxx| 最新中文字幕2018| 黄色一级二级三级| 啊啊啊国产视频| 成人亚洲精品777777大片| 黄色免费视频大全| 欧洲美女和动交zoz0z| 日本日本精品二区免费| 精品国产aⅴ麻豆| 麻豆蜜桃91| 亚洲国产精品综合| 亚洲国产精品www| 亚洲午夜在线观看| 亚洲精品乱码久久久久久蜜桃91| 日韩欧美一区二区三区四区 | 免费在线黄色影片| 成人性生交大片免费看午夜| 美女欧美视频在线观看免费 | 一本久久综合亚洲鲁鲁五月天 | 4hu四虎永久在线影院成人| 黄色美女久久久| 亚洲精品视频在线免费| 国产专区欧美专区| 夜夜亚洲天天久久| 一区二区三区 日韩| 久久99视频免费| 欧美国产在线观看| 九九亚洲精品| 巨骚激情综合| 亚洲美女视频一区| 九九在线视频| 色噜噜狠狠色综合中国| 深夜福利久久| 日韩一区二区三区中文字幕| 亚洲资源av| 91网址在线观看| 六月婷婷激情网| 日韩视频精品在线| 日韩精品视频在线看| 99热99热| 精品福利一二区| 国产91精品免费| 韩国精品福利一区二区三区| 欧美精品成人在线| 国产精品资源| 91白丝在线| 久久人妻精品白浆国产| 国产精品高潮粉嫩av| 欧美日韩视频专区在线播放| 久久精品国产精品青草| 国内不卡的一区二区三区中文字幕| 成人av小说网| 成人av网站观看| 日韩av网址在线| 99久久伊人久久99| 你懂的一区二区三区| 日韩在线资源| 欧美黄网在线观看| 青草青草久热精品视频在线网站| 色综合久久六月婷婷中文字幕| 久久看片网站| 日日夜夜一区| 性视频一区二区三区| 亚洲精品人成| 清纯唯美亚洲激情| 日韩视频一区二区在线观看| 久久夜色精品国产欧美乱极品| 久久国产精品成人免费观看的软件| 色呦呦在线资源| 在线观看高清免费视频| 91日本在线观看| 尤物99国产成人精品视频| 亚洲国产另类精品专区| 成人偷拍自拍| 黄色大片在线看| 国模吧无码一区二区三区| 99电影网电视剧在线观看| 亚洲欧洲国产伦综合| 国产精品久久看| 久久精品人人| 亚洲精品国模| 三级在线观看视频| 97在线资源| 青青在线视频免费观看| 国产精品视频1区| 亚洲性夜色噜噜噜7777| 天天综合天天做天天综合| 成人网在线播放| 在线看片一区| 风间由美中文字幕在线看视频国产欧美 | 99re热这里只有精品免费视频| 你懂的国产精品永久在线| 欧美成人福利| 激情影院在线观看| 色偷偷免费视频| 最近中文字幕免费mv| 亚洲综合最新在线| 91亚洲永久精品| 欧美日韩免费观看一区=区三区| av日韩一区| 国产网红在线观看| 污网站在线看| 99热这里只有精品在线播放| 在线免费观看成人网| www.久久爱.cn| 欧美一区二区三区四区在线| 亚洲天堂成人在线| 欧美日韩一区成人| 一区二区三区成人在线视频| 日本午夜精品一区二区三区电影| 外国成人在线视频| 日本高清不卡一区二区三区视频| 在线视频毛片| 美女av免费在线观看| 国产精品久久久久久久久久久久冷| 欧美日韩国产成人| 精品香蕉一区二区三区| 福利二区91精品bt7086| 国产色综合一区| 精品在线播放午夜| 久久久久久美女精品| 久久国产精品美女| av最新在线| 视频三区在线| 黄网站app在线观看下载视频大全官网| 国产一二三四五| 精品乱码一区| 国产suv精品一区二区| 亚洲性av网站| 欧美一区二区三区在线视频| 亚洲精品中文在线观看| 国产精品亚洲视频| 老色鬼久久亚洲一区二区| 欧美日韩激情在线一区二区三区| 国产精品久久久久久久久久久久久久久 | 国产一区在线视频| 亚洲精品社区| 午夜久久免费观看| 不卡在线一区二区| 日本一道高清一区二区三区| 欧美黄页免费| 韩国精品主播一区二区在线观看 | 都市激情久久综合| 欧美少妇另类| 在线成人一区| 精产国产伦理一二三区| 成视频免费在线看| 369你懂的电影天堂| 国产午夜伦鲁鲁| 日韩精品视频一区二区在线观看| 国产欧美日韩小视频| 中文字幕剧情在线观看一区|