偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

你真的該在 JavaScript 里“多取消”

開發(fā) 前端
某天我在做一個 Web 應(yīng)用:三個?fetch?并發(fā),用戶還沒等結(jié)果出來就切走了頁面。然后呢?這三條請求仍舊跑到完結(jié)——帶寬被浪費(fèi)、CPU 被占用、用戶也得不到任何好處。

某天我在做一個 Web 應(yīng)用:三個 fetch 并發(fā),用戶還沒等結(jié)果出來就切走了頁面。然后呢?這三條請求仍舊跑到完結(jié)——帶寬被浪費(fèi)、CPU 被占用、用戶也得不到任何好處。

那一刻我意識到:異步任務(wù)的“取消”,不是可選項(xiàng),而是必選項(xiàng)。 你是否也經(jīng)歷過這種“用戶一走了之、網(wǎng)絡(luò)卻在后臺堵車”的場景?

我需要一個能及時叫停異步操作的機(jī)制。

接下來看看這個很酷的 JavaScript 能力,如何把異步的生殺大權(quán)交回到你手里——因此應(yīng)用更快、同時用戶更開心、而且服務(wù)器壓力更小。

機(jī)制揭秘:它是如何工作的

主角叫 AbortController。這是控制異步取消的原生 API。

它的思路非常樸素:創(chuàng)建一個 controller,拿到其中的 signal,把這個信號傳給需要“可取消”的異步操作(例如 fetch,也可以是你封裝的自定義異步函數(shù),甚至是計時器)。當(dāng)你在合適的時機(jī)調(diào)用 abort(),所有與該 signal 關(guān)聯(lián)的任務(wù)都會被終止

一個極簡示例:

const controller = new AbortController();
const { signal } = controller;

fetch('/api/data', { signal })
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => {
    if (err.name === 'AbortError') {
      console.log('Fetch canceled');
    }
  });

// 稍后……
controller.abort(); // 取消該次請求

signal 把 fetch 和控制器綁在一起;abort() 一下,立刻“掐斷”。因此,當(dāng)用戶已離場,我們就不必讓請求在后臺無意義地跑完。

真實(shí)場景:搜索請求的“競態(tài)清除”

你可能寫過即時搜索:用戶每敲一個字符就發(fā)一次請求。如果不取消舊請求,競態(tài)隨時發(fā)生——“a”的響應(yīng)可能晚于abc”,最后把正確結(jié)果覆蓋掉了。

用 AbortController,每次新請求發(fā)出時先取消舊的

let controller = null;

function search(query) {
  // 1) 取消上一次未完成的請求
  if (controller) controller.abort();

  // 2) 為本次查詢創(chuàng)建新控制器
  controller = new AbortController();

  fetch(`https://api.example.com/search?q=${query}`, { signal: controller.signal })
    .then(response => response.json())
    .then(data => console.log('Results:', data))
    .catch(err => {
      if (err.name === 'AbortError') return; // 預(yù)期中的取消,不算錯誤
      console.error('Error:', err);
    });
}

// 連續(xù)輸入的模擬
search('cat');
search('cats'); // 'cat' 的請求被取消,只保留最新的

結(jié)果呢?只有最新那次查詢會落地,因此后端不再被“鍵盤風(fēng)暴”轟炸,同時前端也能避免錯亂刷新,從而讓列表穩(wěn)定且準(zhǔn)確。

不止網(wǎng)絡(luò):計時器同樣可控

AbortController絕不是fetch 的專屬。事實(shí)上,你可以把它接到幾乎任何異步流程上。下面是一個“用戶離開就掐掉超時器”的小例子:

const controller = new AbortController();
const { signal } = controller;

function delay(ms, signal) {
  return new Promise((resolve, reject) => {
    const id = setTimeout(resolve, ms);
    signal.addEventListener("abort", () => {
      clearTimeout(id);
      reject(new Error("Timeout canceled"));
    });
  });
}

delay(5000, signal)
  .then(() => console.log("Done"))
  .catch(console.error);

// 在 5 秒之前取消
controller.abort();

這樣一來,不再需要那些“沒人等、卻一直掛著”的計時器;因此副作用更少,而且可回收性更好。

為什么這件事如此重要?

使用 AbortController 會讓你的前端更“干凈”

  • 性能殺掉沒人需要的請求;因此節(jié)省帶寬與 CPU。
  • 體驗(yàn):不再閃爍、不再“過期數(shù)據(jù)”覆蓋新結(jié)果;同時加載狀態(tài)可控。
  • 可控性由你決定哪些異步繼續(xù)、哪些該終止——從而避免連鎖反應(yīng)與資源泄漏。

但也別忽略它的邊界

  • 舊瀏覽器兼容性:在 2018 年之前的環(huán)境里,AbortController 支持并不理想;因此需要 polyfill 或降級策略。
  • 部分 API 不支持 signal:例如某些老的 WebSocket 實(shí)現(xiàn)與第三方 SDK;不過你仍可以在外層封裝一個“軟取消”(即忽略結(jié)果)來達(dá)成類似效果。
  • 團(tuán)隊規(guī)范:取消語義需要貫穿調(diào)用棧;否則容易出現(xiàn)“上層以為取消了、下層仍在跑”的錯位——因此請為自定義異步函數(shù)設(shè)計 signal 參數(shù)妥善傳播

最后的結(jié)論

我曾經(jīng)把無用請求當(dāng)成 Web 的“自然損耗”。而現(xiàn)在,只要是交互密集的頁面,我幾乎不會再寫沒有“取消通道”的異步。

試著在下一個項(xiàng)目里用用 AbortController:因此你的網(wǎng)絡(luò)更清爽,同時用戶看到的內(nèi)容更穩(wěn)定,最終你的應(yīng)用會顯得更專業(yè)。

責(zé)任編輯:武曉燕 來源: 大遷世界
相關(guān)推薦

2019-11-06 09:52:01

JavaScript單線程非阻塞

2022-09-22 14:55:31

前端JavaScripthis

2022-09-26 13:10:17

JavaScriptthis

2021-05-13 10:40:16

ThreadLocal代碼Java

2020-09-10 14:33:18

計算機(jī)

2020-03-31 10:58:38

2021-09-04 23:33:32

996互聯(lián)網(wǎng)加班

2021-01-22 07:48:07

JavaScript 高階函數(shù)閉包

2022-04-07 16:03:36

JavaScriptTypeScript

2021-07-11 18:04:04

C語言

2023-10-16 10:29:51

mysqlMVCC

2019-08-13 08:43:07

JavaScript前端面試題

2015-03-06 09:47:53

小米變化

2013-07-15 16:55:45

2020-04-17 14:25:22

Kubernetes應(yīng)用程序軟件開發(fā)

2022-07-26 00:00:22

HTAP系統(tǒng)數(shù)據(jù)庫

2025-08-06 08:53:35

2014-04-17 16:42:03

DevOps

2020-11-08 14:38:35

JavaScript代碼開發(fā)

2019-08-27 08:24:17

簡歷技能工作
點(diǎn)贊
收藏

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