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

當(dāng)前位置:首頁(yè) > 科技  > 軟件

八個(gè)Promise高級(jí)技巧,讓你在前端開發(fā)中如虎添翼!

來(lái)源: 責(zé)編: 時(shí)間:2024-07-02 17:38:01 224觀看
導(dǎo)讀在JavaScript項(xiàng)目中,Promise 的使用是必不可少的。然而,我發(fā)現(xiàn)許多中高級(jí)前端開發(fā)人員仍然停留在常見(jiàn)的promiseInst.then()、promiseInst.catch()、Promise.all甚至async/await等常規(guī)實(shí)踐上,并沒(méi)有深入理解它們。實(shí)際上,P

在JavaScript項(xiàng)目中,Promise 的使用是必不可少的。然而,我發(fā)現(xiàn)許多中高級(jí)前端開發(fā)人員仍然停留在常見(jiàn)的promiseInst.then()、promiseInst.catch()、Promise.all甚至async/await等常規(guī)實(shí)踐上,并沒(méi)有深入理解它們。Y1w28資訊網(wǎng)——每日最新資訊28at.com

實(shí)際上,Promise 有許多巧妙的高級(jí)用法,其中一些在ALOVA請(qǐng)求策略庫(kù)中廣泛使用。Y1w28資訊網(wǎng)——每日最新資訊28at.com

ALOVA 是一個(gè)基于 Promise 的請(qǐng)求策略庫(kù),旨在幫助開發(fā)者更高效地進(jìn)行 HTTP 請(qǐng)求處理。它通過(guò)高級(jí)的 Promise 技巧,實(shí)現(xiàn)了請(qǐng)求共享、緩存、批量請(qǐng)求等功能,從而簡(jiǎn)化了前端開發(fā)中的數(shù)據(jù)請(qǐng)求管理。ALOVA 的目標(biāo)是提供一種簡(jiǎn)潔、高效的方式來(lái)處理復(fù)雜的請(qǐng)求場(chǎng)景,減少代碼冗余,提高應(yīng)用性能。Y1w28資訊網(wǎng)——每日最新資訊28at.com

現(xiàn)在,我將毫無(wú)保留地分享這些高級(jí)技巧。讀完這篇文章后,將不再為相關(guān)問(wèn)題感到困惑。Y1w28資訊網(wǎng)——每日最新資訊28at.com

串行執(zhí)行Promise數(shù)組

例如,如果你有一組需要串行執(zhí)行的接口,首先你可能會(huì)想到使用 await。Y1w28資訊網(wǎng)——每日最新資訊28at.com

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

如果使用Promise語(yǔ)法,你可以使用then函數(shù)將多個(gè)Promise串起來(lái),從而實(shí)現(xiàn)順序執(zhí)行。Y1w28資訊網(wǎng)——每日最新資訊28at.com

const requestAry = [() => api.request1(), () => api.request2(), () => api.request3()];const finallyPromise = requestAry.reduce(    (currentPromise, nextRequest) => currentPromise.then(() => nextRequest()),    Promise.resolve() // 創(chuàng)建一個(gè)初始Promise以串聯(lián)數(shù)組中的Promise。);

2.在新Promise作用域外改變狀態(tài)

假設(shè)你有一些頁(yè)面上的函數(shù)需要在使用前收集用戶信息,那么你會(huì)如何實(shí)現(xiàn)呢?一種方法是在點(diǎn)擊某個(gè)功能前彈出信息收集對(duì)話框。Y1w28資訊網(wǎng)——每日最新資訊28at.com

不同層次的前端開發(fā)人員有不同的實(shí)現(xiàn)思路:Y1w28資訊網(wǎng)——每日最新資訊28at.com

  • 初級(jí)前端:我會(huì)創(chuàng)建一個(gè)模態(tài)框,然后復(fù)制粘貼到其他頁(yè)面以提高效率!
  • 中級(jí)前端:你的方法不利于維護(hù)。我們應(yīng)該將這個(gè)組件單獨(dú)封裝,并在需要的頁(yè)面中導(dǎo)入使用!
  • 高級(jí)前端:封裝該封裝的!寫在一個(gè)所有頁(yè)面都能調(diào)用的地方,不是更好嗎?

讓我們看看高級(jí)前端是如何實(shí)現(xiàn)的。以Vue3為例,看下面的示例。Y1w28資訊網(wǎng)——每日最新資訊28at.com

<!-- App.vue --><template>  <!-- 以下是模態(tài)組件。 -->  <div class="modal" v-show="visible">    <div>      用戶名:<input v-model="info.name" />    </div>    <!-- 其他信息 -->    <button @click="handleCancel">取消</button>    <button @click="handleConfirm">提交</button>  </div>  <!-- 頁(yè)面組件 --></template><script setup>import { provide } from 'vue';const visible = ref(false);const info = reactive({  name: ''});let resolveFn, rejectFn;// 將信息收集函數(shù)傳遞給以下內(nèi)容。provide('getInfoByModal', () => {  visible.value = true;  return new Promise((resolve, reject) => {    // 將兩個(gè)函數(shù)賦值給外部,突破Promise作用域。    resolveFn = resolve;    rejectFn = reject;  });});const handleConfirm = () => {  resolveFn && resolveFn(info);};const handleCancel = () => {  rejectFn && rejectFn(new Error('用戶已取消。'));};</script>

接下來(lái),直接調(diào)用 getInfoByModal 即可使用模態(tài)框,并輕松獲取用戶填寫的數(shù)據(jù)。Y1w28資訊網(wǎng)——每日最新資訊28at.com

<template>  <button @click="handleClick">填寫信息</button></template><script setup>import { inject } from 'vue';const getInfoByModal = inject('getInfoByModal');const handleClick = async () => {  // 調(diào)用后,會(huì)顯示模態(tài)框。當(dāng)用戶點(diǎn)擊“確認(rèn)”時(shí),Promise會(huì)變?yōu)閒ulfilled狀態(tài),從而獲取用戶信息。  const info = await getInfoByModal();  await api.submitInfo(info);}</script>

這也是許多UI組件庫(kù)中封裝常用組件的方法。Y1w28資訊網(wǎng)——每日最新資訊28at.com

3.async/await的替代用法

許多人只知道在調(diào)用 async function 時(shí)使用 await 接收返回值,但他們不知道async函數(shù)實(shí)際上是返回Promise的函數(shù)。例如,以下兩個(gè)函數(shù)是等價(jià)的:Y1w28資訊網(wǎng)——每日最新資訊28at.com

const fn1 = async () => 1;const fn2 = () => Promise.resolve(1);fn1(); // 同樣返回一個(gè)值為1的Promise對(duì)象。

在大多數(shù)情況下,await 后面跟著的是一個(gè)Promise對(duì)象,并等待其變?yōu)?nbsp;fulfilled 狀態(tài)。因此,下面的函數(shù) fn1 等待也是等價(jià)的:Y1w28資訊網(wǎng)——每日最新資訊28at.com

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

然而,await 有一個(gè)不為人知的秘密。當(dāng)它后面跟的是非Promise對(duì)象的值時(shí),它會(huì)使用 Promise 對(duì)象包裝該值。因此,await 后的代碼總是異步執(zhí)行的。例如:Y1w28資訊網(wǎng)——每日最新資訊28at.com

Promise.resolve().then(() => {  console.log(1);});await 2;console.log(2);// 輸出順序:1 2

等價(jià)于Y1w28資訊網(wǎng)——每日最新資訊28at.com

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

4.使用Promise實(shí)現(xiàn)請(qǐng)求共享

當(dāng)一個(gè)請(qǐng)求已經(jīng)發(fā)送但尚未響應(yīng)時(shí),再次發(fā)出相同請(qǐng)求會(huì)導(dǎo)致浪費(fèi)請(qǐng)求。此時(shí),我們可以與第二個(gè)請(qǐng)求共享第一個(gè)請(qǐng)求的響應(yīng)。Y1w28資訊網(wǎng)——每日最新資訊28at.com

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

以上兩個(gè)請(qǐng)求只會(huì)發(fā)送一次,并同時(shí)接收相同的響應(yīng)值。Y1w28資訊網(wǎng)——每日最新資訊28at.com

那么,請(qǐng)求共享有哪些場(chǎng)景呢?我認(rèn)為有三種:Y1w28資訊網(wǎng)——每日最新資訊28at.com

  • 當(dāng)一個(gè)頁(yè)面同時(shí)渲染多個(gè)內(nèi)部組件獲取數(shù)據(jù)時(shí);
  • 提交按鈕未禁用,用戶連續(xù)多次點(diǎn)擊提交按鈕;
  • 在預(yù)加載數(shù)據(jù)的情況下,進(jìn)入預(yù)加載頁(yè)面前完成預(yù)加載;

這也是Alova的高級(jí)功能之一。實(shí)現(xiàn)請(qǐng)求共享需要使用 Promise 緩存功能。也就是說(shuō),一個(gè)Promise對(duì)象可以通過(guò)多次await調(diào)用獲取數(shù)據(jù)。簡(jiǎn)單的實(shí)現(xiàn)思路如下:Y1w28資訊網(wǎng)——每日最新資訊28at.com

const pendingPromises = {};function request(type, url, data) {  // 使用請(qǐng)求信息作為唯一請(qǐng)求鍵來(lái)緩存正在請(qǐng)求的Promise對(duì)象。  // 具有相同鍵的請(qǐng)求將重用該P(yáng)romise。  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;}

5.如果同時(shí)調(diào)用resolve和reject會(huì)發(fā)生什么?

大家都知道,Promise有三種狀態(tài):pending、fulfilled 和 rejected。但在下面的例子中,Promise 的最終狀態(tài)是什么?Y1w28資訊網(wǎng)——每日最新資訊28at.com

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

正確答案是 fulfilled 狀態(tài)。我們只需記住,一旦Promise從pending狀態(tài)轉(zhuǎn)變?yōu)槠渌麪顟B(tài),就不能再改變。因此,在這個(gè)例子中,調(diào)用 resolve()后,即使調(diào)用 reject(),狀態(tài)也不會(huì)再改變。Y1w28資訊網(wǎng)——每日最新資訊28at.com

6.徹底弄清then/catch/finally的返回值

總結(jié)一句話,上述三個(gè)函數(shù)都會(huì)返回一個(gè)新的 Promise包裝對(duì)象,包裝的值是執(zhí)行回調(diào)函數(shù)的返回值。如果回調(diào)函數(shù)拋出錯(cuò)誤,它將包裝一個(gè)處于 rejected 狀態(tài)的 Promise。這不太容易理解,我們來(lái)看一個(gè)例子:Y1w28資訊網(wǎng)——每日最新資訊28at.com

你可以將它們一個(gè)一個(gè)復(fù)制并在瀏覽器控制臺(tái)中運(yùn)行,以更好地理解。Y1w28資訊網(wǎng)——每日最新資訊28at.com

// then函數(shù)Promise.resolve().then(() => 1); // return 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); // return new Promise(resolve => resolve(2))// catch函數(shù)Promise.reject().catch(() => 3); // return new Promise(resolve => resolve(3))Promise.resolve().catch(() => 4); // 返回值是一個(gè)新的Promise,解析為調(diào)用catch的Promise對(duì)象。// 當(dāng)finally函數(shù)的返回值不是Promise時(shí),返回finally函數(shù)之前的Promise對(duì)象。Promise.resolve().finally(() => {}); // return Promise.resolve()Promise.reject().finally(() => {}); // return Promise.reject()// 當(dāng)finally函數(shù)的返回值是Promise時(shí),等待返回的Promise解析后再返回finally函數(shù)之前的Promise對(duì)象。Promise.resolve(5).finally(() => new Promise(res => {  setTimeout(res, 1000);})); // 返回一個(gè)處于pending狀態(tài)的Promise,1秒后解析為5。Promise.reject(6).finally(() => new Promise(res => {  setTimeout(res, 1000);})); // 返回一個(gè)處于pending狀態(tài)的Promise,1秒后拋出數(shù)字6。

7.then函數(shù)的第二個(gè)回調(diào)與catch回調(diào)有何不同?

Promise中的 then 函數(shù)的第二個(gè)回調(diào)和 catch 函數(shù)在請(qǐng)求失敗時(shí)都會(huì)被觸發(fā)。乍一看,它們似乎沒(méi)有太大區(qū)別,但實(shí)際上,前者無(wú)法捕捉當(dāng)前 then 函數(shù)第一個(gè)回調(diào)函數(shù)中拋出的錯(cuò)誤,而 catch 函數(shù)可以。Y1w28資訊網(wǎng)——每日最新資訊28at.com

Promise.resolve().then(  () => {    throw new Error('成功回調(diào)中的錯(cuò)誤');  },  () => {    // 不會(huì)執(zhí)行  }).catch(reason => {  console.log(reason.message); // 打印“成功回調(diào)中的錯(cuò)誤”});

其原理如前所述,catch 函數(shù)是在 then 函數(shù)返回的 Promise 處于 rejected 狀態(tài)時(shí)調(diào)用的,自然可以捕捉到其錯(cuò)誤。Y1w28資訊網(wǎng)——每日最新資訊28at.com

8.實(shí)現(xiàn)Koa2洋蔥模型中的Promise

Koa2框架引入了洋蔥模型,使你的請(qǐng)求像剝洋蔥一樣逐層處理,按相反順序進(jìn)入和退出層,從而實(shí)現(xiàn)請(qǐng)求的統(tǒng)一前后處理。Y1w28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片Y1w28資訊網(wǎng)——每日最新資訊28at.com

我們看看一個(gè)簡(jiǎn)單的Koa2洋蔥模型:Y1w28資訊網(wǎng)——每日最新資訊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。這種神奇的輸出順序是如何實(shí)現(xiàn)的呢?我用了大約20行代碼實(shí)現(xiàn)了這個(gè)簡(jiǎn)單的實(shí)現(xiàn),巧合的是,它與Koa相似。Y1w28資訊網(wǎng)——每日最新資訊28at.com

接下來(lái),讓我們進(jìn)一步分析。Y1w28資訊網(wǎng)——每日最新資訊28at.com

保存中間件函數(shù),然后在 listen 函數(shù)中接收到請(qǐng)求時(shí)調(diào)用洋蔥模型的執(zhí)行。Y1w28資訊網(wǎng)——每日最新資訊28at.com

function action(koaInstance, ctx) {  // ...}class Koa {  middlewares = [];  use(mid) {    this.middlewares.push(mid);  }  listen(port) {    // 模擬接收請(qǐng)求的偽代碼    http.on('request', ctx => {      action(this, ctx);    });  }}

接收到請(qǐng)求后,從第一個(gè)中間件開始按順序執(zhí)行前置邏輯,調(diào)用 next。Y1w28資訊網(wǎng)——每日最新資訊28at.com

// 開始中間件調(diào)用。function action(koaInstance, ctx) {  let nextMiddlewareIndex = 1; // 標(biāo)識(shí)下一個(gè)執(zhí)行的中間件索引    // 定義next函數(shù)。  function next() {    // 在剝洋蔥之前,調(diào)用next會(huì)調(diào)用下一個(gè)中間件函數(shù)。    const nextMiddleware = middlewares[nextMiddlewareIndex];    if (nextMiddleware) {      nextMiddlewareIndex++;      nextMiddleware(ctx, next);    }  }  // 從第一個(gè)中間件函數(shù)開始執(zhí)行,并傳入ctx和next函數(shù)。  middlewares[0](ctx, next);}

處理“next”之后的后置邏輯Y1w28資訊網(wǎng)——每日最新資訊28at.com

function action(koaInstance, ctx) {  let nextMiddlewareIndex = 1;  function next() {    const nextMiddleware = middlewares[nextMiddlewareIndex];    if (nextMiddleware) {      nextMiddlewareIndex++;      // 這里還添加了一個(gè)return,使中間件函數(shù)的執(zhí)行通過(guò)Promise從后向前連接(建議反復(fù)理解這個(gè)return)。      return Promise.resolve(nextMiddleware(ctx, next));    } else {      // 在最后一個(gè)中間件的前置邏輯執(zhí)行完后,返回的fulfilled Promise將開始執(zhí)行next之后的后置邏輯。      return Promise.resolve();    }  }  middlewares[0](ctx, next);}

Y1w28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-98199-0.html八個(gè)Promise高級(jí)技巧,讓你在前端開發(fā)中如虎添翼!

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 一文搞懂Nginx配置:輕松駕馭多域名管理的實(shí)戰(zhàn)攻略

下一篇: ASP.NET Core 極簡(jiǎn) API 在 .NET 6 中的新特性探索

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
国语精品中文字幕| 久久久久国色av免费观看性色| 国产主播一区| 激情自拍一区| 亚洲国产人成综合网站| 99精品热视频| 欧美一区二区三区精品电影| 久久综合狠狠综合久久综青草| 欧美精品免费看| 国产精品私人影院| 一区二区三区自拍| 99国产一区二区三精品乱码| 亚洲欧美一区在线| 久久综合久久综合这里只有精品| 欧美日本韩国一区二区三区| 国产乱理伦片在线观看夜一区| 亚洲承认在线| 亚洲专区在线| 老妇喷水一区二区三区| 欧美日韩色一区| 国产一区视频在线观看免费| 亚洲精品视频一区二区三区| 欧美亚洲一区二区在线观看| 欧美成人免费va影院高清| 国产精品福利在线| 亚洲高清一二三区| 销魂美女一区二区三区视频在线| 欧美不卡福利| 国产欧美一区二区精品性色| 亚洲精品网站在线播放gif| 午夜影院日韩| 欧美精品在线视频观看| 国产一区二区三区电影在线观看| 99精品欧美一区| 老鸭窝亚洲一区二区三区| 国产精品久久久久久模特| 亚洲高清在线精品| 午夜精品www| 欧美日韩国产综合视频在线观看| 国内自拍一区| 亚洲视频在线一区观看| 美女尤物久久精品| 国产老女人精品毛片久久| 亚洲精品网站在线播放gif| 久久精品123| 国产精品毛片大码女人| 亚洲精品中文在线| 久久综合伊人| 国产美女精品人人做人人爽| 亚洲美女诱惑| 久久久久久免费| 国产精品综合不卡av| 夜色激情一区二区| 免费视频一区| 狠狠入ady亚洲精品| 午夜日韩福利| 国产精品国产福利国产秒拍| 亚洲国产精品久久久久婷婷884| 午夜视频在线观看一区| 欧美视频一区二区| 99国产精品国产精品久久| 欧美69wwwcom| 在线视频观看日韩| 久久亚裔精品欧美| 国产综合视频| 亚洲欧美精品一区| 国产精品第三页| 亚洲视频二区| 欧美特黄视频| 在线视频欧美日韩| 欧美日韩www| 亚洲日本欧美天堂| 欧美成ee人免费视频| 永久免费精品影视网站| 久久久亚洲一区| 韩国av一区二区| 久久久噜噜噜久久久| 国内精品久久久| 久久精品视频导航| 国产综合视频| 久久久999精品免费| 国产亚洲观看| 久久精品人人做人人爽| 国产午夜精品久久| 久久狠狠一本精品综合网| 国产婷婷一区二区| 久久精品导航| 国产一区二区三区久久久久久久久| 欧美在线日韩| 激情亚洲成人| 免费观看30秒视频久久| 亚洲国产天堂久久国产91| 欧美成人午夜| 99re热精品| 欧美日韩国产综合久久| 亚洲午夜影视影院在线观看| 国产精品观看| 欧美一区综合| 激情国产一区二区| 免费成人av资源网| 亚洲麻豆视频| 国产精品毛片在线| 欧美在线日韩在线| 在线不卡亚洲| 欧美日韩国产va另类| 亚洲神马久久| 国产欧美日韩精品一区| 久久精品九九| 亚洲第一精品夜夜躁人人躁| 欧美激情第8页| 制服诱惑一区二区| 国产毛片一区| 久久亚洲精品伦理| 亚洲另类黄色| 国产精品va在线播放我和闺蜜| 亚洲影院在线观看| 国内外成人免费激情在线视频 | 中文精品视频| 国产精品亚洲综合久久| 欧美在线亚洲在线| 亚洲国产午夜| 国产精品久久久久久av下载红粉| 欧美一区二区三区免费视频| 亚洲观看高清完整版在线观看| 欧美日韩第一区| 羞羞视频在线观看欧美| 在线不卡中文字幕| 欧美日韩综合在线| 久久精品国产在热久久| 亚洲精选久久| 国产婷婷色一区二区三区| 欧美大片在线观看| 亚洲一区久久久| 在线日韩成人| 国产精品大片wwwwww| 久久夜色撩人精品| 亚洲视频在线二区| 亚洲国产精品国自产拍av秋霞| 欧美视频在线观看视频极品| 久久久久99| 在线亚洲一区| 在线看片成人| 国产精品丝袜xxxxxxx| 欧美福利视频在线观看| 午夜精品久久久久久久99樱桃| 亚洲国产成人久久| 国产精品免费看| 女人天堂亚洲aⅴ在线观看| 亚洲欧美日韩精品久久久| 亚洲国产一区二区三区a毛片| 国产精品久久久久久久9999 | 国产精品久久一卡二卡| 模特精品在线| 欧美一区午夜精品| 一区二区久久久久| 亚洲国产精品福利| 国产精品视频一| 欧美乱妇高清无乱码| 久久久亚洲高清| 亚洲综合日韩在线| 亚洲美女视频在线免费观看| 激情91久久| 国产精品网站在线| 欧美日韩三级一区二区| 麻豆91精品91久久久的内涵| 香蕉久久夜色精品| 在线综合亚洲| 亚洲欧洲三级电影| 精品999久久久| 国产日韩欧美综合在线| 国产精品久久久久91| 欧美另类videos死尸| 免费成人高清| 久久裸体视频| 欧美在线视频免费播放| 亚洲在线视频| 中国成人黄色视屏| 亚洲美女免费精品视频在线观看| 亚洲电影一级黄| 国外成人在线视频网站| 国产欧美欧洲在线观看| 国产精品久久久久久av下载红粉| 欧美激情综合五月色丁香小说| 久久中文欧美| 久久久久久久网| 久久精品国产视频| 欧美一进一出视频| 亚洲欧美日韩精品久久久久| 亚洲一二三四区| 亚洲调教视频在线观看| 亚洲人成网站777色婷婷| 欧美日韩亚洲免费| 欧美国产日本| 欧美xart系列高清| 美女诱惑一区| 美女精品视频一区| 久久综合福利| 玖玖玖国产精品| 狂野欧美激情性xxxx| 卡一卡二国产精品| 欧美成人dvd在线视频| 欧美xxx成人| 欧美激情一区二区久久久| 欧美精品激情|