自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

你知道嗎?大部分人對(duì)于 Promise 的開發(fā)程度遠(yuǎn)遠(yuǎn)不足 10%!

開發(fā) 前端
大家都知道?Promise?是 JavaScript 的一個(gè)非常強(qiáng)大的特性,但是很多人對(duì)于?Promise?的認(rèn)識(shí)還停留在?網(wǎng)絡(luò)請(qǐng)求上?,而網(wǎng)絡(luò)請(qǐng)求大部分人都用?axios,axios?已經(jīng)幫我們封裝好了,所以自然而然地,大部分人在項(xiàng)目中并沒有過多使用過?Promise?這個(gè)強(qiáng)大的特性。

大家都知道 Promise 是 JavaScript 的一個(gè)非常強(qiáng)大的特性,但是很多人對(duì)于 Promise 的認(rèn)識(shí)還停留在 網(wǎng)絡(luò)請(qǐng)求上 ,而網(wǎng)絡(luò)請(qǐng)求大部分人都用 axios,axios 已經(jīng)幫我們封裝好了,所以自然而然地,大部分人在項(xiàng)目中并沒有過多使用過 Promise 這個(gè)強(qiáng)大的特性。

接下來總結(jié)一下我在項(xiàng)目中用到的 Promise 的場(chǎng)景。

打開彈窗的事件回調(diào)

如下場(chǎng)景,因?yàn)檫壿嫳容^多,我封裝了一個(gè) useModal 的 Hook,并在頁面中去調(diào)用,打開彈窗,打開彈窗的時(shí)候,接收兩個(gè)回調(diào):

  • onSuccess:成功的回調(diào)
  • onError:失敗的回調(diào)

因?yàn)槲倚枰陧撁嬲{(diào)用的時(shí)候,成功和失敗之后都需要在頁面中做一些額外的操作。

圖片圖片

接著我在頁面中去調(diào)用這個(gè) Hook,并使用了 open 方法,傳入兩個(gè)回調(diào)。

圖片圖片

不過后來我想了一下,如果我對(duì)于這個(gè) Modal,只在乎 成功回調(diào) 和 失敗回調(diào) 的話,那可不可以直接 鏈?zhǔn)秸{(diào)用就行了呢?,就類似于下面這樣,有點(diǎn)類似于那些組件庫中的 form.validate 方法,也是返回一個(gè) Promise。

圖片圖片

那么就得借助 Promise 的力量了。

圖片圖片

充當(dāng)發(fā)布訂閱

說到發(fā)布訂閱,大家就想到了 EventBus、EventEmit 這些具備 emit、on 的元素,但是有時(shí)候我們所需要的 發(fā)布訂閱 并不需要這么復(fù)雜。

我們需要的可能只是,頁面1 完成了某件事情后,通知一下 頁面2,僅此而已。

我們需要先封裝一個(gè) onReadyFn 的工具函數(shù),這函數(shù)返回兩個(gè)東西。

  • readyResolve: 一個(gè)resolve函數(shù)
  • onReady: 接收回調(diào)函數(shù),只有在readyResolve執(zhí)行后才會(huì)執(zhí)行

圖片圖片

接著封裝一個(gè) usePage1.ts,用來處理 Page1 的邏輯,并在處理完邏輯后發(fā)布通知。

圖片圖片

圖片圖片

現(xiàn)在通知有了,只需要訂閱即可。

圖片圖片

可以到控制臺(tái)里,看到了這個(gè)運(yùn)行順序是符合我們的預(yù)期的

圖片圖片

檢測(cè)接口請(qǐng)求超時(shí)

我們使用 axios 的時(shí)候可以設(shè)置 timeout 去控制接口的超時(shí)時(shí)間,但是有的項(xiàng)目并沒有用 axios 那咋辦呢?那就得自己去檢測(cè)接口請(qǐng)求超時(shí)啦。

大概思路是這樣的,比如你設(shè)置的超時(shí)時(shí)長(zhǎng)是 2000ms。

  • 讓實(shí)際請(qǐng)求跟一個(gè) 2000ms 的定時(shí)器去賽跑
  • 定時(shí)器先執(zhí)行完,則說明實(shí)際請(qǐng)求超時(shí)了
  • 實(shí)際請(qǐng)求先執(zhí)行完,則說明沒有超時(shí)

說到賽跑,咱們第一時(shí)間可以想到 Promise.race,是的,就是用它來檢測(cè)接口超時(shí)。

圖片圖片

圖片圖片

控制多并發(fā)

提起控制并發(fā),大家應(yīng)該不陌生,我們可以先來看看多并發(fā),再去聊聊為什么要去控制它。

多并發(fā)一般是指多個(gè)異步操作同時(shí)進(jìn)行,而運(yùn)行的環(huán)境中資源是有限的,短時(shí)間內(nèi)過多的并發(fā),會(huì)對(duì)所運(yùn)行的環(huán)境造成很大的壓力,比如前端的瀏覽器,后端的服務(wù)器,常見的多并發(fā)操作有:

  • 前端的多個(gè)接口同時(shí)請(qǐng)求
  • 前端多條數(shù)據(jù)異步處理
  • Nodejs的多個(gè)數(shù)據(jù)操作同時(shí)進(jìn)行
  • Nodejs對(duì)多個(gè)文件同時(shí)進(jìn)行修改

圖片圖片

正是因?yàn)槎嗖l(fā)會(huì)造成壓力,所以我們才需要去控制他,降低這個(gè)壓力~,比如我可以控制最大并發(fā)數(shù)是 3,這樣的話即使有100個(gè)并發(fā),我也能保證最多同時(shí)并發(fā)的最大數(shù)量是 3。

圖片圖片

大致實(shí)現(xiàn)思路就是,假設(shè)現(xiàn)在有 9 個(gè)并發(fā),我設(shè)置最大并發(fā)為 3,那么我將會(huì)走下面這些步驟:

  • 1、先定好三個(gè)坑位
  • 2、讓前三個(gè)并發(fā)進(jìn)去坑位執(zhí)行
  • 3、看哪個(gè)坑位并發(fā)先執(zhí)行完,就從剩余的并發(fā)中拿一個(gè)進(jìn)去補(bǔ)坑
  • 4、一直重復(fù)第 3 步,一直到所有并發(fā)執(zhí)行完

圖片圖片

在進(jìn)行多并發(fā)的時(shí)候,我們通常會(huì)使用 Promise.all ,但是 Promise.all并不能控制并發(fā),或者說它本來就沒這個(gè)能力,我們可以看下面的例子。

圖片圖片

最后是同時(shí)輸出,這說明這幾個(gè)并發(fā)是同時(shí)發(fā)生的。

圖片圖片

期望效果

圖片圖片

圖片圖片

實(shí)現(xiàn) limitFn

我們需要在函數(shù)內(nèi)部維護(hù)兩個(gè)變量:

  • queue:隊(duì)列,用來存每一個(gè)改造過的并發(fā)
  • activeCount:用來記錄正在執(zhí)行的并發(fā)數(shù)

并聲明函數(shù) generator ,這個(gè)函數(shù)返回一個(gè) Promise,因?yàn)?Promise.all 最好是接收一個(gè) Promise 數(shù)組。

圖片圖片

接下來我們來實(shí)現(xiàn) enqueue 這個(gè)函數(shù)做兩件事:

  • 將每一個(gè) fetchFn 放進(jìn)隊(duì)列里
  • 將坑位里的 fetchFn 先執(zhí)行

圖片圖片

假如我設(shè)置最大并發(fā)數(shù)為 2,那么這一段代碼在一開始的時(shí)候只會(huì)執(zhí)行 2 次,因?yàn)橐婚_始只會(huì)有 2 次符合 if 判斷,大家可以思考一下為什么~

圖片圖片

一開始執(zhí)行 2 次,說明這時(shí)候兩個(gè)坑位已經(jīng)各自有一個(gè) fetchFn 在執(zhí)行了。

接下來我們實(shí)現(xiàn) run 函數(shù),這個(gè)函數(shù)是用來包裝 fetch 的,他完成幾件事情:

1、將 activeCount++ ,這時(shí)候執(zhí)行中的并發(fā)數(shù) +1

2、將 fetchFn 執(zhí)行,并把結(jié)果 resolve 出去,說明這個(gè)并發(fā)執(zhí)行完了

3、將 activeCount--,這時(shí)候執(zhí)行中的并發(fā)數(shù) -1

4、從 queue 中取一個(gè)并發(fā),拿來補(bǔ)坑執(zhí)行

圖片圖片

其實(shí)第 3、4 步,是在 next 函數(shù)里面執(zhí)行的

圖片圖片

代碼

充當(dāng)發(fā)布訂閱

// hooks/onReadyFn
export const onReadyFn = () => {
  let readyResolve: any = null;
  const readyPromise = new Promise(resolve => {
    // 把 resolve 保存起來
    readyResolve = resolve;
  });
  const onReady = (cb: (...args: any[]) => void) => {
    readyPromise.then((...args: any[]) => {
      // resolve 執(zhí)行完才會(huì)走 then
      // 才會(huì)執(zhí)行回調(diào)函數(shù)
      cb(...args);
    });
  };

  return {
    onReady,
    readyResolve,
  };
};

接口超時(shí)

// 模擬實(shí)際請(qǐng)求
const fetchFn = (delay: number) => {
  return new Promise<number>(resolve => {
    setTimeout(() => {
      resolve(1);
    }, delay);
  });
};

// 判斷是否超時(shí)
const checkTimeout = (delay: number, timeout: number) => {
  return Promise.race([
    fetchFn(delay),
    new Promise((_, reject) => {
      setTimeout(() => {
        reject('超時(shí)啦!');
      }, timeout);
    }),
  ]);
};

// 沒超時(shí)
checkTimeout(100, 500)
  .then(res => {
    console.log('沒超時(shí)', res);
  })
  .catch(err => {
    console.log(err);
  });

// 超時(shí)了
checkTimeout(600, 500)
  .then(res => {
    console.log('沒超時(shí)', res);
  })
  .catch(err => {
    console.log(err);
  });

控制并發(fā)

const limitFn = (limit) => {
  const queue = [];
  let activeCount = 0;

  const next = () => {
    activeCount--;

    if (queue.length > 0) {
      queue.shift()();
    }
  };

  const run = async (fn, resolve, ...args) => {
    activeCount++;

    const result = (async () => fn(...args))();


    try {
      const res = await result;
      resolve(res);
    } catch { }

    next();
  };

  const enqueue = (fn, resolve, ...args) => {
    queue.push(run.bind(null, fn, resolve, ...args));

    if (activeCount < limit && queue.length > 0) {
      queue.shift()();
    }
  };

  const generator = (fn, ...args) =>
    new Promise((resolve) => {
      enqueue(fn, resolve, ...args);
    });

  return generator;
};

責(zé)任編輯:武曉燕 來源: 前端之神
相關(guān)推薦

2011-12-26 17:13:18

iPad統(tǒng)計(jì)App

2024-08-01 17:34:56

Promiseaxios請(qǐng)求

2012-06-07 16:16:43

JavaScript

2018-11-25 21:53:10

人工智能AI開發(fā)者

2025-01-26 16:04:09

2019-06-14 15:36:13

Windows 10安全PC

2016-10-26 10:23:42

2022-05-18 09:49:26

MySQLID數(shù)據(jù)庫

2016-12-22 08:38:21

2023-02-07 13:51:11

SQLupdate語句

2018-08-31 07:33:58

2015-11-25 10:48:44

JS閉包面試題

2023-12-12 08:41:01

2024-04-15 00:04:00

APP開發(fā)

2021-10-14 06:52:47

算法校驗(yàn)碼結(jié)構(gòu)

2024-09-18 07:00:00

消息隊(duì)列中間件消息隊(duì)列

2022-09-29 15:32:58

云計(jì)算計(jì)算模式

2024-08-06 11:27:23

LLM鏈系統(tǒng)AI

2024-11-20 08:31:49

前端全棧技術(shù)

2024-04-07 00:00:00

ESlint命令變量
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)