cxxjackie 发表于 2022-7-23 12:14:11

ajax封装库

本帖最后由 cxxjackie 于 2022-10-15 22:48 编辑

一个脚本专用的ajax封装库,集成了GM\_xmlhttpRequest和XMLHttpRequest。当运行环境中存在GM\_xmlhttpRequest或GM.xmlHttpRequest时,请求将自动使用他们,否则使用XMLHttpRequest(指定`_mode`参数可改变这一行为)。

**注意:库本身没有声明脚本权限的能力,必要的油猴参数仍需要在自己的脚本中声明,如@grant GM\_xmlhttpRequest和@connect。**

## 发送请求

使用ajax函数发送请求,使用示例:

```js
const json = await ajax('https://www.example.com/', {
    method: 'post',
    data: {
      message: 'hello world'
    },
    responseType: 'json',
    _nocatch: true
})
```

ajax函数接收两个参数,第一个参数为url,第二个参数为请求的配置对象(可省),返回值为包含响应内容的Promise(取决于`_detail`参数)。配置对象的参数说明如下:

`method`
默认值get。不区分大小写。

`data`
post请求下,data和Content-Type具有自适应的特点。

若未指定Content-Type:
**data为字符串时:**
Content-Type将被自动设置为application/x-www-form-urlencoded。

**data为普通的简单对象时:**
转换为以&拼接的url字符串,Content-Type设置为application/x-www-form-urlencoded。

**data为嵌套对象的简单对象时:**
转换为json字符串,Content-Type设置为application/json。

**其他情况(FormData、Blob等):**
Content-Type留空,由浏览器自动处理。

若指定了以下Content-Type:

**application/x-www-form-urlencoded:**
非字符串的data将被转换为url字符串。

**application/json:**
非字符串的data将被转换为json字符串。

特别地,get请求也可以指定data,数据将被转换为url字符串并拼接到url中,可以在数据较多时写成对象形式并利用此特性。

`responseType`
默认值text。指定响应类型,若为json将尽可能解析为对象(部分请求的json字符串可能被序列化多次),解析失败发生错误。**对于旧版油猴的document和旧版脚本猫的text、json等bug表现均做了兼容处理。**

`其他受GM_xhr和xhr支持的参数`
请自行查询相关文档(注意两者支持的参数不尽相同),不受支持的参数将被忽略。

以下参数由库内部管理,因此必定被忽略:
`onload`
`onerror`
`onabort`
`ontimeout`

以下参数是此库特有的:
`_mode`
规定请求使用的API,应是以下字符串之一:
GM\_xmlhttpRequest、GM\_xhr、GM.xmlHttpRequest、GM.xhr、XMLHttpRequest、xhr

`_status`
默认值。一个包含成功状态码的数组,通常情况下只有状态码为200才被认为是成功的,否则视为错误。如果你想指定其他状态码为成功响应,将其加入此数组。

`_nocatch`
默认值false。规定是否不对返回的Promise做错误处理(即不发生reject),若为true且发生错误,Promise将不再抛出错误,而是返回null(受`_detail`影响)。这一参数主要用于async/await模式,可避免频繁的try...catch语句。
**注意**:即便`_nocatch`为true,当请求404或因跨域等问题失败时,控制台仍可能抛出错误。这是xhr的设计所致,此类错误无法通过脚本捕获,但不阻塞代码的运行。

`_detail`
默认值false。为false时,返回值即响应内容;为true时,返回包含响应信息的对象,包括finalUrl、status、response和responseHeaders。若`_nocatch`和`_detail`均为true,发生错误时将返回错误信息,包括url、status和error。

## 默认配置

当ajax的第一个参数为字符串`default`时,函数功能改为指定默认配置,后续请求的配置对象将与默认配置合并。示例:

```js
ajax('default', {
    method: 'post',
    responseType: 'json',
    _nocatch: true
});
ajax('https://www.example.com/', {
    data: {
      message: 'hello'
    }
});
ajax('https://www.example.com/', {
    data: {
      message: 'world'
    }
});
```

## 中断请求

当ajax的第一个参数为字符串`abort`时,函数功能改为中断请求,第二个参数必须是请求返回的Promise。示例:

```js
const request = ajax('https://www.example.com/', {
    onreadystatechange: xhr => {
      if (xhr.readyState === 2) {
            ajax('abort', request);
      }
    }
});
```

**注意**:在GM\_xmlhttpRequest中,响应较快的请求可能导致abort不生效;在GM.xmlHttpRequest中,abort必定不生效;旧版脚本猫无法abort。这些均是脚本管理器自身的问题,意味着**中断命令并不总是可靠的**。

## 更新日志

**1.0.0** 初始版本
**1.0.1** 优化错误信息的toString函数。
**1.0.2** 对响应头中的重复字段做合并处理。

王一之 发表于 2022-7-23 12:20:44

我之前也封装过一个:https://github.com/scriptscat/lib/blob/main/src/gm/README.md

(我以为没论坛发帖子就发评分了,原来论坛帖子按钮不知道怎么顶到右边去了)

cxxjackie 发表于 2022-7-23 12:32:45

王一之 发表于 2022-7-23 12:20
我之前也封装过一个:https://github.com/scriptscat/lib/blob/main/src/gm/README.md

(我以为没论坛发帖 ...

我看过那个,这个没用axios,基本是按我自己的使用习惯来封的,顺便处理了一些兼容问题。

cocang 发表于 2022-7-24 12:06:57

GGNB!!!

李恒道 发表于 2022-7-24 18:21:47

cocang 发表于 2022-7-24 12:06
GGNB!!!

好久没看到哥哥写脚本了!

琦玉 发表于 2022-8-16 09:33:49

请问大佬,这个跟XMLHttpRequest有什么不同?

王一之 发表于 2022-8-16 09:43:08

琦玉 发表于 2022-8-16 09:33
请问大佬,这个跟XMLHttpRequest有什么不同?

一个脚本专用的ajax封装库,集成了GM_xmlhttpRequest和XMLHttpRequest。当运行环境中存在GM_xmlhttpRequest或GM.xmlHttpRequest时,请求将自动使用他们,否则使用XMLHttpRequest(指定_mode参数可改变这一行为)。

Major 发表于 2023-2-23 17:17:30

这个库存 怎样发送 header 和 cookies

cxxjackie 发表于 2023-2-23 20:34:59

Major 发表于 2023-2-23 17:17
这个库存 怎样发送 header 和 cookies

跟GM_xhr一样,所有没提到的参数用法都与原API一致:
ajax('https://www.example.com/', {
    headers: {
      cookie: 'hello=world'
    }
});
cookie也可以提到外面来:
ajax('https://www.example.com/', {
    headers: {}
    cookie: 'hello=world'
});

player 发表于 2023-6-9 14:03:51

我突然发现了一个问题,我有两个脚本都是match同一网址的。我有一个脚本是声明了@grant GM_xmlhttpRequest和@connect,另一个没有。我把声明了的脚本关了,然而没声明的脚本ajax一样能请求到数据。。。
页: [1] 2
查看完整版本: ajax封装库