日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

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

來源: 責編: 時間:2024-01-02 17:27:34 209觀看
導讀我發現很多人只知道如何常規地使用promise。在js項目中,promise的使用應該是必不可少的,但我發現在同事和面試官中,很多中級以上的前端仍然堅持promiseInst.then()、promiseInst.catch()、Promise等常規用法等等。即使是

我發現很多人只知道如何常規地使用promise。zQT28資訊網——每日最新資訊28at.com

zQT28資訊網——每日最新資訊28at.com

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

但實際上,Promise 有很多巧妙的高級用法,并且一些高級用法在 alova 請求策略庫內部也被廣泛使用。zQT28資訊網——每日最新資訊28at.com

現在,我將與大家分享8個高級使用技巧。希望這些技巧能夠對你有所幫助,現在,我們就開始吧。zQT28資訊網——每日最新資訊28at.com

1. Promise數組的串行執行

例如,如果你有一組接口需要串行執行,你可能首先想到使用await。zQT28資訊網——每日最新資訊28at.com

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

如果使用promise,可以使用then函數串聯多個promise,實現串行執行。zQT28資訊網——每日最新資訊28at.com

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 范圍之外更改狀態

假設你有多個頁面,其功能要求在允許使用之前收集用戶信息。 點擊使用某個功能之前,會彈出一個彈框進行信息收集。 你會如何實施這個?zQT28資訊網——每日最新資訊28at.com

以下是不同級別前端同學的實現思路:zQT28資訊網——每日最新資訊28at.com

初級前端:我寫一個模態框,然后復制粘貼到其他頁面。 效率非常高!zQT28資訊網——每日最新資訊28at.com

中級前端:這個不好維護。 我們需要單獨封裝這個組件,并在需要的頁面引入!zQT28資訊網——每日最新資訊28at.com

高級前端:安裝任何密封的東西! ! ! 把方法調用寫在所有頁面都可以調用的地方不是更好嗎?zQT28資訊網——每日最新資訊28at.com

想要了解高級前端是如何實現的,以vue3為例,看一下下面的例子。zQT28資訊網——每日最新資訊28at.com

<!-- 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 followingprovide('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就可以通過直接調用模態框來輕松獲取用戶填寫的數據。zQT28資訊網——每日最新資訊28at.com

<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組件庫中封裝常用組件的一種方式。zQT28資訊網——每日最新資訊28at.com

3. async/await 的替代用法

很多人只知道它是用來在調用await時接收async函數的返回值的,卻不知道async函數它實際上是一個返回promise的函數。 例如,以下兩個函數是等效的:zQT28資訊網——每日最新資訊28at.com

const fn1 = async () => 1;const fn2 = () => Promise.resolve(1);fn1(); // Also returns a promise object with a value of 1

在大多數情況下,await 會跟隨 Promise 對象并等待它完全填充。 因此,下面的 fn1 函數 wait 也是等價的:zQT28資訊網——每日最新資訊28at.com

await fn1();const promiseInst = fn1();await promiseInst;

然而,await也有一個鮮為人知的秘密。 當它后面跟的值不是promise對象時,它會用promise對象包裝該值,所以await后面的代碼必須異步執行。 例子:zQT28資訊網——每日最新資訊28at.com

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

相當于zQT28資訊網——每日最新資訊28at.com

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

4. 承諾實施請求共享

當一個請求已經發出但尚未得到響應時,再次發出相同的請求,就會造成請求的浪費。 此時,我們可以將第一個請求的響應與第二個請求共享。zQT28資訊網——每日最新資訊28at.com

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

上述兩個請求實際上只發送一次,同時收到相同的響應值。zQT28資訊網——每日最新資訊28at.com

那么,請求共享有哪些使用場景呢? 我認為有以下三個:zQT28資訊網——每日最新資訊28at.com

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

這也是alova的高級功能之一。 要實現請求共享,需要使用promise的緩存功能,即一個promise對象可以通過多次await獲取數據。 簡單的實現思路如下:zQT28資訊網——每日最新資訊28at.com

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;}

上述兩個請求實際上只發送一次,同時收到相同的響應值。zQT28資訊網——每日最新資訊28at.com

那么,請求共享有哪些使用場景呢? 我認為有以下三個:zQT28資訊網——每日最新資訊28at.com

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

這也是alova的高級功能之一。 要實現請求共享,需要使用promise的緩存功能,即一個promise對象可以通過多次await獲取數據。 簡單的實現思路如下:zQT28資訊網——每日最新資訊28at.com

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

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

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

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

我們可以將它們一一復制到瀏覽器控制臺并運行它們以幫助理解。zQT28資訊網——每日最新資訊28at.com

// then functionPromise.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 functionPromise.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可以。zQT28資訊網——每日最新資訊28at.com

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 上調用的,因此它的錯誤自然可以被捕獲。zQT28資訊網——每日最新資訊28at.com

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

koa2框架引入了洋蔥模型,可以讓你的請求像剝洋蔥一樣一層層進去,再一層層出來,從而實現請求前后處理的統一。zQT28資訊網——每日最新資訊28at.com

zQT28資訊網——每日最新資訊28at.com

我們來看一個簡單的 koa2 洋蔥模型:zQT28資訊網——每日最新資訊28at.com

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行左右的代碼就實現了。 如有雷同,純屬巧合。zQT28資訊網——每日最新資訊28at.com

接下來我們分析一下zQT28資訊網——每日最新資訊28at.com

注:以下內容對新手不友好,請謹慎閱讀。zQT28資訊網——每日最新資訊28at.com

首先先保存中間件函數,在listen函數中收到請求后調用洋蔥模型執行。zQT28資訊網——每日最新資訊28at.com

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之前的前置邏輯。zQT28資訊網——每日最新資訊28at.com

//Start to start middleware callfunction 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邏輯zQT28資訊網——每日最新資訊28at.com

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);}

至此,一個簡單的洋蔥模型就已經實現了。zQT28資訊網——每日最新資訊28at.com

總結

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

本文鏈接:http://www.www897cc.com/showinfo-26-56393-0.html八個關于 Promise 的高級用途的技巧

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 九部門:推廣農村客運車輛代運郵件快件,拓展“農村客貨郵 +”

下一篇: Cython庫:從基本用法到高級用法

標簽:
  • 熱門焦點
  • 石頭自清潔掃拖機器人G10S評測:多年黑科技集大成之作 懶人終極福音

    科技圈經常能看到一個詞叫“縫合怪”,用來形容那些把好多功能或者外觀結合在一起的產品,通常這樣的詞是貶義詞,但如果真的是產品縫合的好、縫合的實用的話,那它就成了中性詞,今
  • CSS單標簽實現轉轉logo

    轉轉品牌升級后更新了全新的Logo,今天我們用純CSS來實現轉轉的新Logo,為了有一定的挑戰性,這里我們只使用一個標簽實現,將最大化的使用CSS能力完成Logo的繪制與動畫效果。新logo
  • 微信語音大揭秘:為什么禁止轉發?

    大家好,我是你們的小米。今天,我要和大家聊一個有趣的話題:為什么微信語音不可以轉發?這是一個我們經常在日常使用中遇到的問題,也是一個讓很多人好奇的問題。讓我們一起來揭開這
  • 破圈是B站頭上的緊箍咒

    來源 | 光子星球撰文 | 吳坤諺編輯 | 吳先之每年的暑期檔都少不了瞄準追劇女孩們的古偶劇集,2021年有優酷的《山河令》,2022年有愛奇藝的《蒼蘭訣》,今年卻輪到小破站抓住了追
  • 新電商三兄弟,“抖快紅”成團!

    來源:價值研究所作 者:Hernanderz 隨著內容電商的概念興起,抖音、快手、小紅書組成的&ldquo;新電商三兄弟&rdquo;成為業內一股不可忽視的勢力,給阿里、京東、拼多多帶去了巨大壓
  • 小米MIX Fold 3下月亮相:今年唯一無短板的全能折疊屏

    這段時間以來,包括三星、一加、榮耀等等有不少品牌旗下的最新折疊屏旗艦都有新的進展,其中榮耀、三星都已陸續發布了最新的折疊屏旗艦,尤其號榮耀Magi
  • 三星Galaxy Z Fold5今日亮相:厚度縮減但仍略顯厚重

    據官方此前宣布,三星將于7月26日也就是今天在韓國首爾舉辦Unpacked活動,屆時將帶來帶來包括Galaxy Buds 3、Galaxy Watch 6、Galaxy Tab S9、Galaxy
  • SN570 NVMe SSD固態硬盤 價格與性能兼具

    SN570 NVMe SSD固態硬盤是西部數據發布的最新一代WD Blue系列的固態硬盤,不僅閃存技術更為精進,性能也得到了進一步的躍升。WD Blue SN570 NVMe SSD的包裝外
  • 華為舉行春季智慧辦公新品發布會 首次推出電子墨水屏平板

    北京時間2月27日晚,華為在巴塞羅那舉行春季智慧辦公新品發布會,在海外市場推出之前已經在中國市場上市的筆記本、平板、激光打印機等辦公產品,并首次推出搭載
Top 主站蜘蛛池模板: 苍南县| 乐陵市| 右玉县| 威海市| 光山县| 霍城县| 宜君县| 惠来县| 上饶县| 方山县| 哈巴河县| 阳朔县| 石嘴山市| 汝南县| 八宿县| 丹阳市| 新巴尔虎右旗| 无极县| 望江县| 阳新县| 安陆市| 麻江县| 大城县| 新民市| 盖州市| 昭觉县| 静海县| 永年县| 米泉市| 萨嘎县| 盖州市| 罗甸县| 连州市| 崇州市| 新蔡县| 墨竹工卡县| 金昌市| 浦北县| 南涧| 建宁县| 塔城市|