优秀的编程知识分享平台

网站首页 > 技术文章 正文

我就不信我搞不明白取消请求(想要请求撤销)

nanyue 2024-09-06 20:24:13 技术文章 11 ℃

# 我就不信我搞不明白取消请求:详解前端异步操作的取消机制

**导语:**

在网络请求频繁的现代Web前端开发中,如何有效地管理和取消未完成的HTTP请求是一项重要的技能。面对用户行为的瞬息万变,及时取消不再需要的请求,不仅有助于提升用户体验,还能避免不必要的资源浪费。本文将以“我就不信我搞不明白取消请求”为切入点,深入探讨前端开发中如何利用Promise、AbortController等机制实现请求的灵活取消,并辅以实例代码加以说明。

---

### **一、问题背景:为何需要取消HTTP请求?**

**标题:卡顿、冗余与性能瓶颈,揭示取消请求的重要性**

在网页交互过程中,用户常常在发出一个请求后迅速改变操作意图,比如点击刷新页面、跳转至其他页面或者改变了搜索条件。若不及时取消先前发出但尚未得到响应的请求,可能会导致以下几个问题:

- 页面响应迟钝,因为浏览器仍在等待旧请求的结果;

- 浪费服务器资源,处理无意义的过期请求;

- 数据冗余,接收并处理了用户实际上不需要的响应数据。

---

### **二、基于Promise的简单尝试**

**标题: Promise 的局限性与初步解决方案**

尽管原生Promise并不直接支持取消,我们可以通过模拟状态的方式构建一种可取消的Promise。但是请注意,这种方法并非标准做法,仅用于理解原理。

```javascript

class CancellablePromise extends Promise {

constructor(executor, onCancel) {

super((resolve, reject) => {

this.cancelled = false;

const execute = () => executor(resolve, reject);

this.abort = () => {

this.cancelled = true;

// 可在此处添加取消实际请求的操作

};

onCancel && onCancel(this.abort);

execute();

});

}

}

// 使用示例

const cancellableFetch = new CancellablePromise(

(resolve, reject) => {

fetch('https://api.example.com/data')

.then(response => {

if (!this.cancelled) resolve(response.json());

})

.catch(error => !this.cancelled && reject(error));

},

abortFn => { // 提供取消回调函数

//...

}

);

// 用户触发取消操作

cancellableFetch.abort();

```

---

### **三、借助AbortController规范取消HTTP请求**

**标题:拥抱标准,AbortController轻松掌控请求生死**

ES2019引入了AbortController接口,它提供了符合规范的取消异步操作的方法,特别适用于取消fetch或XMLHttpRequest发起的HTTP请求。

```javascript

// 创建AbortController实例

const controller = new AbortController();

// 获取AbortSignal对象

const signal = controller.signal;

// 发起fetch请求并传入signal

fetch('https://api.example.com/data', { signal })

.then(response => response.json())

.catch(error => {

// 检查错误是否由于请求被取消引发

if (error.name === 'AbortError') {

console.log('请求已被取消');

} else {

throw error;

}

});

// 当需要取消请求时

controller.abort();

// 或者绑定取消事件监听

signal.addEventListener('abort', () => {

console.log('请求已被取消');

});

```

---

### **四、在实际场景中合理应用AbortController**

**标题:从单一请求到并发请求池,全面掌握取消策略**

在复杂的前端应用中,可能同时存在多个并发请求。这时,可以建立一个请求队列或池,并通过AbortController统一管理各个请求的生命周期。

```javascript

let activeControllers = [];

function makeCancelableFetch(url) {

const controller = new AbortController();


// 将当前控制器放入活跃列表

activeControllers.push(controller);

return fetch(url, { signal: controller.signal })

.then(response => response.json())

.finally(() => {

// 请求结束后从活跃列表移除控制器

const index = activeControllers.indexOf(controller);

if (index > -1) activeControllers.splice(index, 1);

});

}

// 用户触发页面离开或其它需要取消所有请求的事件

function cancelAllRequests() {

activeControllers.forEach(controller => controller.abort());

activeControllers = [];

}

```

---

**结语:**

通过对Promise和AbortController的理解与实践,我们可以更好地管理前端应用程序中的HTTP请求,从而解决因请求无法取消带来的各种问题。掌握这一关键技巧,将使我们的前端应用更加健壮、响应迅速,也使得我们在复杂多变的用户交互场景下游刃有余。所以,只要我们深入学习并实践,“取消请求”这个难题,确实没什么搞不明白的!接下来,就让我们一起运用这项技术,打造更为流畅、高效的Web应用吧!

最近发表
标签列表