返回顶部
分享到

AJAX常见的几种封装方法实例介绍

相关技巧 来源:互联网 作者:佚名 发布时间:2025-07-08 22:00:56 人浏览
摘要

AJAX (Asynchronous JavaScript and XML) 封装是为了简化重复的异步请求代码,提高开发效率和代码复用性。下面我将介绍几种常见的 AJAX 封装方式。 方法1. 基于原生 XMLHttpRequest 的封装 XMLHttpRequest。其主

AJAX (Asynchronous JavaScript and XML) 封装是为了简化重复的异步请求代码,提高开发效率和代码复用性。下面我将介绍几种常见的 AJAX 封装方式。

方法1. 基于原生 XMLHttpRequest 的封装

XMLHttpRequest。其主要特点如下:

  1. 实现动态不刷新,通过异步?式,提升?户体验,优化了浏览器和服务器之间的传输。
  2. 把?部分原本由服务器负担的?作转移到客户端,利?客户端闲置的资源进?处理,减轻服务器和带宽的负担,节约空间和成本。
  3. ?刷新更新??,?户不?再像以前?样在服务器处理数据时,只能在死板的?屏前焦急的等待。AJAX使?XMLHttpRequest对象发送请求并得到服务器响应,在不需要重新载?整个??的情况下,就可以通过DOM及时将更新的内容显示在??上。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

/**

 * 基于原生XHR的AJAX封装

 * @param {Object} options 配置对象

 * @param {string} options.url 请求地址

 * @param {string} [options.method='GET'] 请求方法

 * @param {Object} [options.data=null] 请求数据

 * @param {Object} [options.headers={}] 请求头

 * @param {function} [options.success] 成功回调

 * @param {function} [options.error] 失败回调

 */

function ajax(options) {

  const xhr = new XMLHttpRequest();

  const method = options.method || 'GET';

  let url = options.url;

  let data = options.data || null;

 

  // 处理GET请求的查询参数

  if (method === 'GET' && data) {

    const params = new URLSearchParams();

    for (const key in data) {

      params.append(key, data[key]);

    }

    url += '?' + params.toString();

    data = null;

  }

 

  xhr.open(method, url, true);

 

  // 设置请求头

  if (options.headers) {

    for (const key in options.headers) {

      xhr.setRequestHeader(key, options.headers[key]);

    }

  }

 

  xhr.onreadystatechange = function() {

    if (xhr.readyState === 4) {

      if (xhr.status >= 200 && xhr.status < 300) {

        let response = xhr.responseText;

        try {

          response = JSON.parse(response);

        } catch (e) {}

        options.success && options.success(response);

      } else {

        options.error && options.error(xhr.status, xhr.statusText);

      }

    }

  };

 

  xhr.onerror = function() {

    options.error && options.error(-1, 'Network Error');

  };

 

  // 发送请求

  if (data && typeof data === 'object') {

    xhr.setRequestHeader('Content-Type', 'application/json');

    xhr.send(JSON.stringify(data));

  } else {

    xhr.send(data);

  }

}

 

// 使用示例

ajax({

  url: '/api/user',

  method: 'POST',

  data: { name: 'John', age: 30 },

  headers: {

    'Authorization': 'Bearer token123'

  },

  success: function(response) {

    console.log('Success:', response);

  },

  error: function(status, statusText) {

    console.error('Error:', status, statusText);

  }

});

方法2. 基于 Fetch API 的封装

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

/**

 * 基于Fetch API的AJAX封装

 * @param {string} url 请求地址

 * @param {Object} [options={}] 请求配置

 * @returns {Promise} 返回Promise对象

 */

function fetchAjax(url, options = {}) {

  const defaultOptions = {

    method: 'GET',

    headers: {

      'Content-Type': 'application/json'

    },

    credentials: 'same-origin', // 携带cookie

    ...options

  };

 

  // 处理GET请求的查询参数

  if (defaultOptions.method === 'GET' && defaultOptions.body) {

    const params = new URLSearchParams();

    for (const key in defaultOptions.body) {

      params.append(key, defaultOptions.body[key]);

    }

    url += '?' + params.toString();

    delete defaultOptions.body;

  }

 

  // 处理非GET请求的body数据

  if (defaultOptions.body && typeof defaultOptions.body === 'object') {

    defaultOptions.body = JSON.stringify(defaultOptions.body);

  }

 

  return fetch(url, defaultOptions)

    .then(async response => {

      const data = await response.json().catch(() => ({}));

      if (!response.ok) {

        const error = new Error(response.statusText);

        error.response = response;

        error.data = data;

        throw error;

      }

      return data;

    });

}

 

// 使用示例

fetchAjax('/api/user', {

  method: 'POST',

  body: { name: 'John', age: 30 },

  headers: {

    'Authorization': 'Bearer token123'

  }

})

.then(data => console.log('Success:', data))

.catch(err => console.error('Error:', err));

方法 3. 基于 Axios 风格的封装

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

class Ajax {

  constructor(baseURL = '', timeout = 10000) {

    this.baseURL = baseURL;

    this.timeout = timeout;

    this.interceptors = {

      request: [],

      response: []

    };

  }

 

  request(config) {

    // 处理请求拦截器

    let chain = [this._dispatchRequest, undefined];

    this.interceptors.request.forEach(interceptor => {

      chain.unshift(interceptor.fulfilled, interceptor.rejected);

    });

    this.interceptors.response.forEach(interceptor => {

      chain.push(interceptor.fulfilled, interceptor.rejected);

    });

 

    let promise = Promise.resolve(config);

    while (chain.length) {

      promise = promise.then(chain.shift(), chain.shift());

    }

    return promise;

  }

 

  _dispatchRequest(config) {

    return new Promise((resolve, reject) => {

      const xhr = new XMLHttpRequest();

      let url = config.baseURL ? config.baseURL + config.url : config.url;

      let data = config.data;

 

      // 处理GET请求参数

      if (config.method === 'GET' && data) {

        const params = new URLSearchParams();

        for (const key in data) {

          params.append(key, data[key]);

        }

        url += '?' + params.toString();

        data = null;

      }

 

      xhr.timeout = config.timeout || 10000;

      xhr.open(config.method, url, true);

 

      // 设置请求头

      if (config.headers) {

        for (const key in config.headers) {

          xhr.setRequestHeader(key, config.headers[key]);

        }

      }

 

      xhr.onload = function() {

        if (xhr.status >= 200 && xhr.status < 300) {

          let response = xhr.responseText;

          try {

            response = JSON.parse(response);

          } catch (e) {}

          resolve({

            data: response,

            status: xhr.status,

            statusText: xhr.statusText,

            headers: xhr.getAllResponseHeaders()

          });

        } else {

          reject(new Error(`Request failed with status code ${xhr.status}`));

        }

      };

 

      xhr.onerror = function() {

        reject(new Error('Network Error'));

      };

 

      xhr.ontimeout = function() {

        reject(new Error('Timeout'));

      };

 

      // 发送请求

      if (data && typeof data === 'object') {

        xhr.setRequestHeader('Content-Type', 'application/json');

        xhr.send(JSON.stringify(data));

      } else {

        xhr.send(data);

      }

    });

  }

 

  get(url, config = {}) {

    return this.request({

      ...config,

      method: 'GET',

      url

    });

  }

 

  post(url, data, config = {}) {

    return this.request({

      ...config,

      method: 'POST',

      url,

      data

    });

  }

 

  // 添加拦截器

  useRequestInterceptor(fulfilled, rejected) {

    this.interceptors.request.push({ fulfilled, rejected });

    return this.interceptors.request.length - 1;

  }

 

  useResponseInterceptor(fulfilled, rejected) {

    this.interceptors.response.push({ fulfilled, rejected });

    return this.interceptors.response.length - 1;

  }

 

  // 移除拦截器

  ejectRequestInterceptor(id) {

    if (this.interceptors.request[id]) {

      this.interceptors.request.splice(id, 1);

    }

  }

 

  ejectResponseInterceptor(id) {

    if (this.interceptors.response[id]) {

      this.interceptors.response.splice(id, 1);

    }

  }

}

 

// 使用示例

const api = new Ajax('https://api.example.com');

 

// 添加请求拦截器

api.useRequestInterceptor(config => {

  config.headers = config.headers || {};

  config.headers['Authorization'] = 'Bearer token123';

  return config;

});

 

// 添加响应拦截器

api.useResponseInterceptor(response => {

  console.log('Response:', response);

  return response.data;

}, error => {

  console.error('Error:', error);

  return Promise.reject(error);

});

 

// 发起请求

api.get('/user/123')

  .then(data => console.log('User data:', data))

  .catch(err => console.error('Error:', err));

 

api.post('/user', { name: 'John', age: 30 })

  .then(data => console.log('Created user:', data))

  .catch(err => console.error('Error:', err));

4. 封装要点总结

统一接口:提供一致的调用方式,如get(), post()等方法

参数处理:

GET请求自动拼接查询参数

POST请求自动处理Content-Type

拦截器机制:支持请求/响应拦截

错误处理:统一错误处理逻辑

Promise支持:返回Promise便于链式调用

超时处理:设置合理的请求超时时间

扩展性:支持自定义配置和拦截器

5. 实际项目中的增强功能

1.自动重试机制:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

function withRetry(fn, retries = 3, delay = 1000) {

  return function(...args) {

    return new Promise((resolve, reject) => {

      function attempt(retryCount) {

        fn(...args)

          .then(resolve)

          .catch(err => {

            if (retryCount < retries) {

              setTimeout(() => attempt(retryCount + 1), delay);

            } else {

              reject(err);

            }

          });

      }

      attempt(0);

    });

  };

}

 

// 使用示例

const ajaxWithRetry = withRetry(ajax, 3, 1000);

2.请求取消功能:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

function createCancelToken() {

  let cancel;

  const token = new Promise((resolve, reject) => {

    cancel = reject;

  });

  return { token, cancel };

}

 

// 在请求中检查取消token

function ajaxWithCancel(options) {

  const { token, cancel } = createCancelToken();

  const xhr = new XMLHttpRequest();

   

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

    // ...正常请求逻辑

     

    // 检查取消

    token.catch(err => {

      xhr.abort();

      reject(err);

    });

  });

   

  return { promise, cancel };

}

3.请求缓存:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

const cache = new Map();

 

function cachedAjax(options) {

  const cacheKey = JSON.stringify(options);

   

  if (cache.has(cacheKey)) {

    return Promise.resolve(cache.get(cacheKey));

  }

   

  return ajax(options).then(response => {

    cache.set(cacheKey, response);

    return response;

  });

}

根据项目需求选择合适的封装方式,小型项目可使用简单封装,大型项目建议使用成熟的库如Axios。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • 一文介绍php、jsp、asp和aspx的区别(小科普)
    通俗理解 PHP 通俗:PHP就像万能胶,专为快速搭建中小型网站设计。它语法简单(类似C语言),免费且跨平台,适合新手和中小项目,比如
  • Trae AI IDE的使用教程(全网最全)

    Trae AI IDE的使用教程(全网最全)
    Trae AI IDE 全网最全的使用教程 近期,字节发布了一款 AI Coding 产品 Trae,它是一款对标 Cursor 和 Windsurf 的全新 IDE,也是一款真正为中文开发
  • AJAX常见的几种封装方法实例介绍

    AJAX常见的几种封装方法实例介绍
    AJAX (Asynchronous JavaScript and XML) 封装是为了简化重复的异步请求代码,提高开发效率和代码复用性。下面我将介绍几种常见的 AJAX 封装方式。
  • Windows环境git配置多个ssh的实现

    Windows环境git配置多个ssh的实现
    Windows 环境下解决 SSH 连接 GitHub 要求密码的问题 在 Windows 环境下解决 SSH 连接 GitHub 持续要求密码的问题需要特别注意 Windows 系统的特性。以
  • 浏览器插件cursor实现自动注册、续杯的过程

    浏览器插件cursor实现自动注册、续杯的过程
    无需下载、安装任何软件,浏览器实现无限续杯 我认为最强的武功就是用自己打败自己,就在刚刚根据从一个佬那里得来的思想,我决定用
  • Git配置SSH密钥与私钥的教程(跨平台完整指南)
    在使用 Git 进行版本控制时,SSH 是一种安全、高效的认证方式。通过配置 SSH 密钥对(公钥和私钥),我们可以免去每次操作远程仓库时输入
  • git stash命令基本用法介绍
    git stash是 Git 中一个非常有用的命令,它可以临时保存当前工作区的修改,让你可以切换到其他分支或者处理其他任务,而不需要提交这些还
  • 如何快速解决连接git/github失败的问题

    如何快速解决连接git/github失败的问题
    Git连接出错 完成基础配置后,始终不能进行git push/git clone,ping github.com 总是显示往 127.0.0.1 发送测试包 镜像法 关于解决git clone问题可以直
  • git进阶之hooks勾子脚本介绍
    Git Hooks是Git的一个重要特性,它允许用户在Git仓库中定义一些自动化的脚本,这些脚本可以在特定的Git事件(如提交代码、接收代码等)发
  • git如何查看提交行数、删除行数
    统计指定用户提交代码情况 1 git log --author=你的名字 --pretty=tformat: --numstat | awk { add += $1; subs += $2; loc += $1 - $2 } END { printf added lines: %s, remove
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计