一篇快速上手 Axios,一个基于 Promise 的网络请求库(涉及原理实现)

news2024/11/24 13:40:43

Axios

  • 1. 介绍
    • 1.1 什么是 Axios?
    • 1.2 axios 和 ajax 的区别
  • 2. 安装使用
  • 3. Axios 基本使用
    • 3.1 Axios 发送请求
    • 3.2 其他方式发送请求
    • 3.3 响应结构
    • 3.4 Request Config
    • 3.5 默认配置
      • 3.6 创建实例对象发送请求
    • 3.7 拦截器
    • 3.8 取消请求
  • 4. 模拟 Axios
    • 4.1 axios 对象创建过程模拟实现
    • 4.2 axios 发送请求模拟实现
    • 4.3 axios 拦截器功能模拟实现
    • 4.4 axios 取消请求功能模拟实现

1. 介绍

https://www.axios-http.cn/

1.1 什么是 Axios?

Axios 是一个 基于 Promise 的 HTTP 库,适用于 node.js 浏览器。它是同构的(= 它可以以相同的代码库在浏览器和 Node.js 中运行)。在服务器端,它使用原生的 Node.js http模块,而在客户端(浏览器)上,它使用 XMLHttpRequests。

Axios 是一个基于 promise 的网络请求库,可以用于浏览器和 node.js中。Axios(相比于原生的XMLHttpRequest对象来说) 简单易用,(相比于jQuery)axios包尺寸小且提供了易于扩展的接口,是专注于网络请求的库。

axios(ajax i/o system)不是一种新技术,本质上也是对原生XHR(XMLHttpReques)的封装,只不过它是基于Promise的,是Promise的实现版本,符合最新的ES规范。

1.2 axios 和 ajax 的区别

  1. axios是通过 promise 实现对 ajax 技术的一种封装,而 ajax 则是实现了网页的局部数据刷新。
  2. axios 可以说是 ajax,而 ajax 不止是axios。
  3. 用法相同,但个别参数不同。

2. 安装使用

npm安装

 npm install axios

通过cdn引入

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

在 vue 项目的 main.js 文件中引入axios

import axios from 'axios'
Vue.prototype.$axios = axios

在组件中使用axios

<script>
	export default {
		mounted(){
			this.$axios.get('/goods.json').then(res=>{
				console.log(res.data);
			})
		}
	}
</script>

3. Axios 基本使用

3.1 Axios 发送请求

const btns = document.querySelectorAll('button');

// 获取文章
btns[0].onclick = function () {
    // 发送 AJAX 请求
    axios({
        method: 'GET',
        url: 'http://localhost:3000/posts/3',
    }).then(response => {
        console.log(response);
    });
};

// 添加一篇文章
btns[1].onclick = function () {
    // 发送 AJAX 请求
    axios({
        method: 'POST',
        url: 'http://localhost:3000/posts',
        // 请求体
        data: {
            title: '今天天气不错',
            author: '张三',
        },
    }).then(response => {
        console.log(response);
    });
};

// 更新数据
btns[2].onclick = function () {
    // 发送 AJAX 请求
    axios({
        method: 'PUT',
        url: 'http://localhost:3000/posts/3',
        // 请求体
        data: {
            title: '今天天气不错',
            author: '李四',
        },
    }).then(response => {
        console.log(response);
    });
};

// 删除数据
btns[3].onclick = function () {
    // 发送 AJAX 请求
    axios({
        method: 'DELETE',
        url: 'http://localhost:3000/posts/3',
    }).then(response => {
        console.log(response);
    });
};

3.2 其他方式发送请求

axios.request(config)

axios.get(url[, config])

axios.delete(url[, config])

axios.head(url[, config])

axios.options(url[, config])

axios.post(url[, data[, config]])

axios.put(url[, data[, config]])

axios.patch(url[, data[, config]])

// 发送 GET 请求
btns[0].onclick = function () {
    axios.request({
        method: 'GET',
        url: 'http://localhost:3000/comments',
    }).then(response => {
        console.log(response);
    });
};

// 发送 POST 请求
btns[1].onclick = function () {
    axios.post(
        'http://localhost:3000/comments',
        {
            'text': '我爱Axios',
            'postId': 2,
        },
    ).then(response => {
        console.log(response);
    });
};

// 同理
......

3.3 响应结构

在这里插入图片描述

{
  // `data` 由服务器提供的响应
  data: {},

  // `status` 来自服务器响应的 HTTP 状态码
  status: 200,

  // `statusText` 来自服务器响应的 HTTP 状态信息
  statusText: 'OK',

  // `headers` 是服务器响应头
  // 所有的 header 名称都是小写,而且可以使用方括号语法访问
  // 例如: `response.headers['content-type']`
  headers: {},

  // `config` 是 `axios` 请求的配置信息
  config: {},

  // `request` 是生成此响应的请求
  // 在node.js中它是最后一个ClientRequest实例 (in redirects),
  // 在浏览器中则是 XMLHttpRequest 实例
  request: {}
}

3.4 Request Config

{
  // `url` 是用于请求的服务器 URL
  url: '/user',

  // `method` 是创建请求时使用的方法
  method: 'get', // 默认值

  // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
  // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
  baseURL: 'https://some-domain.com/api/',

  // `transformRequest` 允许在向服务器发送前,修改请求数据
  // 它只能用于 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  // 数组中最后一个函数必须返回一个字符串, 一个Buffer实例,ArrayBuffer,FormData,或 Stream
  // 你可以修改请求头。
  transformRequest: [function (data, headers) {
    // 对发送的 data 进行任意转换处理

    return data;
  }],

  // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
  transformResponse: [function (data) {
    // 对接收的 data 进行任意转换处理

    return data;
  }],

  // 自定义请求头
  headers: {'X-Requested-With': 'XMLHttpRequest'},

  // `params` 是与请求一起发送的 URL 参数
  // 必须是一个简单对象或 URLSearchParams 对象
  params: {
    ID: 12345
  },

  // `paramsSerializer`是可选方法,主要用于序列化`params`
  // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
  paramsSerializer: function (params) {
    return Qs.stringify(params, {arrayFormat: 'brackets'})
  },

  // `data` 是作为请求体被发送的数据
  // 仅适用 'PUT', 'POST', 'DELETE 和 'PATCH' 请求方法
  // 在没有设置 `transformRequest` 时,则必须是以下类型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 浏览器专属: FormData, File, Blob
  // - Node 专属: Stream, Buffer
  data: {
    firstName: 'Fred'
  },
  
  // 发送请求体数据的可选语法
  // 请求方式 post
  // 只有 value 会被发送,key 则不会
  data: 'Country=Brasil&City=Belo Horizonte',

  // `timeout` 指定请求超时的毫秒数。
  // 如果请求时间超过 `timeout` 的值,则请求会被中断
  timeout: 1000, // 默认值是 `0` (永不超时)

  // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials: false, // default

  // `adapter` 允许自定义处理请求,这使测试更加容易。
  // 返回一个 promise 并提供一个有效的响应 (参见 lib/adapters/README.md)。
  adapter: function (config) {
    /* ... */
  },

  // `auth` HTTP Basic Auth
  auth: {
    username: 'janedoe',
    password: 's00pers3cret'
  },

  // `responseType` 表示浏览器将要响应的数据类型
  // 选项包括: 'arraybuffer', 'document', 'json', 'text', 'stream'
  // 浏览器专属:'blob'
  responseType: 'json', // 默认值

  // `responseEncoding` 表示用于解码响应的编码 (Node.js 专属)
  // 注意:忽略 `responseType` 的值为 'stream',或者是客户端请求
  // Note: Ignored for `responseType` of 'stream' or client-side requests
  responseEncoding: 'utf8', // 默认值

  // `xsrfCookieName` 是 xsrf token 的值,被用作 cookie 的名称
  xsrfCookieName: 'XSRF-TOKEN', // 默认值

  // `xsrfHeaderName` 是带有 xsrf token 值的http 请求头名称
  xsrfHeaderName: 'X-XSRF-TOKEN', // 默认值

  // `onUploadProgress` 允许为上传处理进度事件
  // 浏览器专属
  onUploadProgress: function (progressEvent) {
    // 处理原生进度事件
  },

  // `onDownloadProgress` 允许为下载处理进度事件
  // 浏览器专属
  onDownloadProgress: function (progressEvent) {
    // 处理原生进度事件
  },

  // `maxContentLength` 定义了node.js中允许的HTTP响应内容的最大字节数
  maxContentLength: 2000,

  // `maxBodyLength`(仅Node)定义允许的http请求内容的最大字节数
  maxBodyLength: 2000,

  // `validateStatus` 定义了对于给定的 HTTP状态码是 resolve 还是 reject promise。
  // 如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),
  // 则promise 将会 resolved,否则是 rejected。
  validateStatus: function (status) {
    return status >= 200 && status < 300; // 默认值
  },

  // `maxRedirects` 定义了在node.js中要遵循的最大重定向数。
  // 如果设置为0,则不会进行重定向
  maxRedirects: 5, // 默认值

  // `socketPath` 定义了在node.js中使用的UNIX套接字。
  // e.g. '/var/run/docker.sock' 发送请求到 docker 守护进程。
  // 只能指定 `socketPath` 或 `proxy` 。
  // 若都指定,这使用 `socketPath` 。
  socketPath: null, // default

  // `httpAgent` and `httpsAgent` define a custom agent to be used when performing http
  // and https requests, respectively, in node.js. This allows options to be added like
  // `keepAlive` that are not enabled by default.
  httpAgent: new http.Agent({ keepAlive: true }),
  httpsAgent: new https.Agent({ keepAlive: true }),

  // `proxy` 定义了代理服务器的主机名,端口和协议。
  // 您可以使用常规的`http_proxy` 和 `https_proxy` 环境变量。
  // 使用 `false` 可以禁用代理功能,同时环境变量也会被忽略。
  // `auth`表示应使用HTTP Basic auth连接到代理,并且提供凭据。
  // 这将设置一个 `Proxy-Authorization` 请求头,它会覆盖 `headers` 中已存在的自定义 `Proxy-Authorization` 请求头。
  // 如果代理服务器使用 HTTPS,则必须设置 protocol 为`https`
  proxy: {
    protocol: 'https',
    host: '127.0.0.1',
    port: 9000,
    auth: {
      username: 'mikeymike',
      password: 'rapunz3l'
    }
  },

  // see https://axios-http.com/zh/docs/cancellation
  cancelToken: new CancelToken(function (cancel) {
  }),

  // `decompress` indicates whether or not the response body should be decompressed 
  // automatically. If set to `true` will also remove the 'content-encoding' header 
  // from the responses objects of all decompressed responses
  // - Node only (XHR cannot turn off decompression)
  decompress: true // 默认值

}

3.5 默认配置

您可以指定应用于每个请求的配置默认值

const btns = document.querySelectorAll('button');

// 默认配置
axios.defaults.method = 'GET';  // 设置默认的请求类型为 GET
axios.defaults.baseURL = 'http://localhost:3000';   // 设置基础 URL
axios.defaults.params = {id: 100};  // 请求参数
axios.defaults.timeout = 3000;  // 超时时间
..... 	// 类似的,可以默认设置 Request Config 里的其他配置属性

btns[0].onclick = function () {
    axios({
        url: '/posts',
    }).then(response => {
        console.log(response);
    });
};

3.6 创建实例对象发送请求

// 创建实例对象
const p = axios.create({
    baseURL: 'http://localhost:3000',
    timeout: 2000,
});

p({
    url: '/posts',
}).then(response => {
    console.log(response);
});

3.7 拦截器

// 设置拦截器
axios.interceptors.request.use(function (config) {
    console.log('请求拦截器,成功');
    return config;
}, function (error) {
    console.log('请求拦截器,失败');
    return Promise.reject(error);
});

// 设置响应拦截器
axios.interceptors.response.use(function (response) {
    console.log('响应拦截器,成功');
    return response;
}, function (error) {
    console.log('响应拦截器,失败');
    return Promise.reject(error);
});

// 发送请求
axios({
    method: 'GET',
    url: 'http://localhost:3000/posts',
}).then(response => {
    console.log('Success!!!');
});

3.8 取消请求

在某些情况下(例如网络连接不可用),提前取消连接对 axios调用大有裨益。如果不取消,axios 调用可能会挂起,直到父代码/堆栈超时(在服务器端应用程序中可能需要几分钟)。

要终止 axios 调用,您可以使用以下方法:

  • signal
  • cancelToken
// 获取按钮
const btns = document.querySelectorAll('button');

let cancel = null;

// 发送请求
btns[0].onclick = function () {
    // 检测上一次请求是否已经完成
    if (cancel !== null) {
        // 取消上一次请求
        cancel();
    }
    axios({
        method: 'GET',
        url: 'http://localhost:3000/posts',
        // 添加配置对象的属性
        cancelToken: new axios.CancelToken(function (c) {
            cancel = c;
        }),
    }).then(response => {
        console.log(response);
    });
};

// 取消请求
btns[1].onclick = function () {
    cancel();
};

4. 模拟 Axios

4.1 axios 对象创建过程模拟实现

// 构造函数
function Axios(config) {
    // 初始化
    this.defaults = config; // 为了创建 default 默认属性
    this.intercepters = {
        request: {},
        response: {},
    };
}

// 原型添加相关的方法
Axios.prototype.request = function (config) {
    console.log('发送 AJAX 请求,类型为 ' + config.method);
};
Axios.prototype.get = function (config) {
    return this.request({method: 'GET'});
};
Axios.prototype.post = function (config) {
    return this.request({method: 'POST'});
};

// 声明函数
function createInstance(config) {
    // 实例化一个对象
    let context = new Axios(config);    // 可以 context.get(), context.post() ...
    // 创建请求函数
    let instance = Axios.prototype.request.bind(context);   // instance 是一个函数,可以 instance({})
    // 将 Axios.prototype 对象中的方法添加到 instance 函数对象中
    Object.keys(Axios.prototype).forEach(key => {
        instance[key] = Axios.prototype[key].bind(context);
    });
    // 为 instance 函数对象添加 default 与 interceptors
    Object.keys(context).forEach(key => {
        instance[key] = context[key];
    });

    return instance;
}

// 创建 axios 对象
let axios = createInstance({method: 'GET'});

// 发送请求
axios({method: 'GET'});
axios.get({});
axios.post({});

4.2 axios 发送请求模拟实现

// 1.声明构造函数
function Axios(config) {
    this.config = config;
}

Axios.prototype.request = function (config) {
    // 发送请求
    let promise = Promise.resolve(config);
    let chains = [dispatchRequest, undefined];  // undefined 占位
    let result = promise.then(chains[0], chains[1]);

    return result;
};

// 2.dispatchRequest 函数
function dispatchRequest(config) {
    // 调用适配器发送请求
    return xhrAdapter(config).then(response => {
        return response;
    }, error => {
        throw error;
    });
}

// 3.adapter 适配器
function xhrAdapter(config) {
    return new Promise((resolve, reject) => {
        // 发送 AJAX 请求
        let xhr = new XMLHttpRequest();
        xhr.open(config.method, config.url);
        xhr.send();
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    resolve({
                        config: config,
                        data: xhr.response,
                        headers: xhr.getAllResponseHeaders(),
                        request: xhr,
                        status: xhr.status,
                        statusText: xhr.statusText,
                    });
                } else {
                    reject(new Error('请求失败 状态码为' + xhr.status));
                }
            }
        };
    });
}

// 4.创建 axios 函数
let axios = Axios.prototype.request.bind(null);

axios({
    method: 'GET',
    url: 'http://localhost:3000/posts',
}).then(response => {
    console.log(response);
});

4.3 axios 拦截器功能模拟实现

chains 中的函数压入情况

在这里插入图片描述

// 构造函数
function Axios(config) {
    this.config = config;
    this.interceptors = {
        request: new InterceptorManager(),
        response: new InterceptorManager(),
    };
}

// 发送请求
Axios.prototype.request = function (config) {
    // 创建一个 promise 对象
    let promise = Promise.resolve(config);
    // 创建一个数组
    const chains = [dispatchRequest, undefined];
    /*
        * 处理拦截器
        * 1.请求拦截器:压入 chains 前面
        * 2.处理拦截器:压入 chains 后面
        * */
    this.interceptors.request.handlers.forEach(item => {
        chains.unshift(item.fulfilled, item.rejected);
    });
    this.interceptors.response.handlers.forEach(item => {
        chains.push(item.fulfilled, item.rejected);
    });

    // 遍历
    while (chains.length > 0) {
        promise = promise.then(chains.shift(), chains.shift());
    }

    return promise;
};

// 发送请求
function dispatchRequest() {
    return new Promise((resolve, reject) => {
        resolve({
            status: 200,
            statusText: 'OK',
        });
    });
}

// 创建实例
let context = new Axios({});
// 创建 axios 函数
let axios = Axios.prototype.request.bind(context);
// 将 context 内部属性 config, interceptors 加到 axios 函数身上
Object.keys(context).forEach(key => {
    axios[key] = context[key];
});

// 拦截器管理器构造函数
function InterceptorManager() {
    this.handlers = [];
}

InterceptorManager.prototype.use = function (fulfilled, rejected) {
    this.handlers.push({
        fulfilled,
        rejected,
    });
};


----------------------------- 测试代码 -----------------------------
// 设置拦截器
axios.interceptors.request.use(function one(config) {
    console.log('请求拦截器 1 Success');
    return config;
}, function one(error) {
    console.log('请求拦截器 1 Error');
    return Promise.reject(error);
});
axios.interceptors.request.use(function two(config) {
    console.log('请求拦截器 2 Success');
    return config;
}, function two(error) {
    console.log('请求拦截器 2 Error');
    return Promise.reject(error);
});

// 设置响应拦截器
axios.interceptors.response.use(function one(response) {
    console.log('响应拦截器 1 Success');
    return response;
}, function one(error) {
    console.log('响应拦截器 1 Error');
    return Promise.reject(error);
});
axios.interceptors.response.use(function two(response) {
    console.log('响应拦截器 2 Success');
    return response;
}, function two(error) {
    console.log('响应拦截器 2 Error');
    return Promise.reject(error);
});

// 发送请求
axios({
    method: 'GET',
    url: 'http://localhost:3000/posts',
}).then(response => {
    console.log(response);
});

运行结果:

在这里插入图片描述

4.4 axios 取消请求功能模拟实现

// 构造函数
function Axios(config) {
    this.config = config;
}

// 原型 request 方法
Axios.prototype.request = function (config) {
    return dispatchRequest(config);
};

// dispatchRequest 函数
function dispatchRequest(config) {
    return xhrAdapter(config);
}

// xhrAdapter
function xhrAdapter(config) {
    // 发送 AJAX 请求
    return new Promise((resolve, reject) => {
        // 实例化对象
        const xhr = new XMLHttpRequest();
        // 初始化
        xhr.open(config.method, config.url);
        // 发送
        xhr.send();
        // 处理结果
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    resolve({
                        status: xhr.status,
                        statusText: xhr.statusText,
                    });
                } else {
                    reject(new Error('请求失败'));
                }
            }
        };
        // 关于取消请求的处理
        if (config.cancelToken) {
            // 对 cancelToken 对象身上的 promise 对象指定成功的回调
            config.cancelToken.promise.then(value => {
                // 取消请求
                xhr.abort();
                // 将整体结果设置为失败
                reject(new Error('请求已经被取消'));
            });
        }
    });
}

// 创建 axios 函数
const context = new Axios({});
const axios = Axios.prototype.request.bind(context);
console.dir(axios);

// CancelToken 构造函数
function CancelToken(executor) {
    var resolvePromise;
    // 为实例对象添加属性
    this.promise = new Promise((resolve) => {
        // 将 resolve 赋值给 resolvePromise
        resolvePromise = resolve;
    });
    // 调用 executor 函数
    executor(function () {
        // 执行 resolvePromise 函数
        resolvePromise();
    });
}

----------------------------- 测试代码 -----------------------------
// 获取按钮
const btns = document.querySelectorAll('button');

// 全局变量 cancel (导火索)
let cancel = null;

// 发送请求
btns[0].onclick = function () {
    // 检测上一次请求是否已经完成
    if (cancel !== null) {
        // 取消上一次请求
        cancel();
    }

    // 创建 cancelToken 的值
    let cancelToken = new CancelToken(function (c) {
        cancel = c;
    });

    axios({
        method: 'GET',
        url: 'http://localhost:3000/posts',
        // 添加配置对象的属性
        cancelToken: cancelToken,
    }).then(response => {
        console.log(response);
    });
};

// 取消请求
btns[1].onclick = function () {
    cancel();
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2246686.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java项目实战II基于SpringBoot前后端分离的网吧管理系统(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着互联网技术的不断发展…

【微软:多模态基础模型】(4)统一视觉模型

欢迎关注[【youcans的AGI学习笔记】](https://blog.csdn.net/youcans/category_12244543.html&#xff09;原创作品 【微软&#xff1a;多模态基础模型】&#xff08;1&#xff09;从专家到通用助手 【微软&#xff1a;多模态基础模型】&#xff08;2&#xff09;视觉理解 【微…

动态规划算法--01背包问题详细讲解步骤

举个例子 要确定哪些物品被放入背包以达到最大价值&#xff0c;可以在计算 dp 数组的同时记录选择的物品。具体来说&#xff0c;可以使用一个额外的数组来记录每个状态的选择情况。以下是一个详细的步骤和代码实现&#xff1a; n 3 W 5 weights [2, 1, 3] values [6, 3…

Jenkins的环境部署

day22 回顾 Jenkins 简介 官网Jenkins Jenkins Build great things at any scale The leading open source automation server, Jenkins provides hundreds of plugins to support building, deploying and automating any project. 用来构建一切 其实就是用Java写的一个项目…

微软发布Win11 24H2系统11月可选更新KB5046740!

系统之家11月22日报道&#xff0c;微软针对Win11 24H2系统推出2024年11月最新可选更新补丁KB5046740&#xff0c;更新后系统版本后升至26100.2454&#xff0c;此次更新后修复当应用程序以PDF和XLSX格式导出图表对象时停止响应、无法使用API查找旋转信息等问题。以下小编将给大家…

JavaEE 实现 登录+注册(采用注解方式链接数据库)

&#xff08;Spring MVC的Controller练习&#xff09; 工具&#xff1a;Tomcat 10.0.23&#xff0c;MySQL&#xff0c;JDK18 一、运行效果展示 点击运行Tomcat首先进入index.jsp页面 若已有账号点击登录即可进行登录&#xff0c;这里先点击“获取ROY6账号”去注册&#xff0…

用 React18 构建点击计分小游戏

本教程将带你创建一个简单的点击计分游戏&#xff0c;使用 React 和基本的 Hooks。游戏规则很简单&#xff1a;在 10 秒内尽可能多地点击按钮以获取高分。 项目结构 确保你的项目结构如下&#xff1a; 编写 ClickGame 组件 在 src/ClickGame.js 文件中&#xff0c;编写如下…

Halo 正式开源: 使用可穿戴设备进行开源健康追踪

在飞速发展的可穿戴技术领域&#xff0c;我们正处于一个十字路口——市场上充斥着各式时尚、功能丰富的设备&#xff0c;声称能够彻底改变我们对健康和健身的方式。 然而&#xff0c;在这些光鲜的外观和营销宣传背后&#xff0c;隐藏着一个令人担忧的现实&#xff1a;大多数这些…

数据结构:链表进阶

链表进阶 1. ArrayList的缺陷2. 链表2.1 链表的概念及结构2.2 链表的实现 3.链表面试题4.LinkedList的使用5.1 什么是LinkedList4.2 LinkedList的使用 5. ArrayList和LinkedList的区别 1. ArrayList的缺陷 通过源码知道&#xff0c;ArrayList底层使用数组来存储元素&#xff1…

第二十二周机器学习笔记:动手深度学习之——线性代数

第二十周周报 摘要Abstract一、动手深度学习1. 线性代数1.1 标量1.2 向量1.3 矩阵1.4 张量1.4.1 张量算法的基本性质 1.5 降维1.5.1 非降维求和 1.6 点积1.6.1 矩阵-向量积1.6.2 矩阵-矩阵乘法 1.7 范数 总结 摘要 本文深入探讨了深度学习中的数学基础&#xff0c;特别是线性代…

Flink-Source的使用

Data Sources 是什么呢&#xff1f;就字面意思其实就可以知道&#xff1a;数据来源。 Flink 做为一款流式计算框架&#xff0c;它可用来做批处理&#xff0c;也可以用来做流处理&#xff0c;这个 Data Sources 就是数据的来源地。 flink在批/流处理中常见的source主要有两大类…

分公司如何纳税

分公司不进行纳税由总公司汇总纳税“子公司具有法人资格&#xff0c;依法独立承担民事责任;分公司不具有法人资格&#xff0c;其民事责任由公司承担。”企业设立分支机构&#xff0c;使其不具有法人资格&#xff0c;且不实行独立核算&#xff0c;则可由总公司汇总缴纳企业所得税…

亚马逊搜索关键词怎么写?

在亚马逊这个全球领先的电子商务平台&#xff0c;如何让自己的产品被更多的消费者发现&#xff0c;是每一个卖家都需要深入思考的问题。而搜索关键词&#xff0c;作为连接卖家与买家的桥梁&#xff0c;其重要性不言而喻。那么&#xff0c;如何撰写有效的亚马逊搜索关键词呢&…

跨视角差异-依赖网络用于体积医学图像分割|文献速递-生成式模型与transformer在医学影像中的应用

Title 题目 Cross-view discrepancy-dependency network for volumetric medical imagesegmentation 跨视角差异-依赖网络用于体积医学图像分割 01 文献速递介绍 医学图像分割旨在从原始图像中分离出受试者的解剖结构&#xff08;例如器官和肿瘤&#xff09;&#xff0c;并…

基本功能实现

目录 1、环境搭建 2、按键控制灯&电机 LED 电机 垂直按键(机械按键) 3、串口调试功能 4、定时器延时和定时器中断 5、振动强弱调节 6、万年历 7、五方向按键 1、原理及分析 2、程序设计 1、环境搭建 需求: 搭建一个STM32F411CEU6工程 分析: C / C 宏定义栏…

C++11新特性探索:Lambda表达式与函数包装器的实用指南

文章目录 前言&#x1f349;一、Lambda表达式&#xff08;匿名函数&#xff09;&#x1f353;1.1 Lambda 表达式的基本语法&#x1f353;1.2 示例&#xff1a;基本 Lambda 表达式&#x1f353;1.3 捕获列表&#xff08;Capture&#xff09;&#x1f353;1.4 使用 Lambda 表达式…

msvcp110.dll丢失修复的多种科学方法分析,详细解析msvcp110.dll文件

遇到“msvcp110.dll丢失”的错误时&#xff0c;这表明你的系统缺少一个关键文件&#xff0c;但解决这一问题比较直接。本文将指导你通过几个简单的步骤迅速修复此错误&#xff0c;确保你的程序或游戏可以顺利运行。接下来的操作将非常简洁明了&#xff0c;易于理解和执行。 一.…

HDR视频技术之四:HDR 主要标准

HDR 是 UHD 技术中最重要维度之一&#xff0c;带来新的视觉呈现体验。 HDR 技术涉及到采集、加工、传输、呈现等视频流程上的多个环节&#xff0c;需要定义出互联互通的产业标准&#xff0c;以支持规模化应用和部署。本文整理当前 HDR 应用中的一些代表性的国际标准。 1 HDR 发…

Bug Fix 20241122:缺少lib文件错误

今天有朋友提醒才突然发现 gitee 上传的代码存在两个很严重&#xff0c;同时也很低级的错误。 因为gitee的默认设置不允许二进制文件的提交&#xff0c; 所以PH47框架下的库文件&#xff08;各逻辑层的库文件&#xff09;&#xff0c;以及Stm32Cube驱动的库文件都没上传到Gi…

c++源码阅读__smart_ptr__正文阅读

文章目录 简介源码解析1. 引用计数的实现方式2. deleter静态方法的赋值时间节点3.make_smart的实现方式 与 好处4. 几种构造函数4.1 空构造函数4.2 接收指针的构造函数4.3 接收指针和删除方法的构造函数 , 以及auto进行模板lambda的编写4.4 拷贝构造函数4.5 赋值运算符 5. rele…