axios网络请求框架源码解析

早期axios0.1.0版本做了对IE浏览器与包含XmlHttpRequest的浏览器的支持。并且做了对请求参数拼接、Json对象序列化等基本功能。

到0.19.0版本时,内部请求已经变为了在Node环境下与主流浏览器的支持,其中Node环境下支持http请求与https请求。并且支持取消、拦截。

Axios执行开始之初,首先执行createInstance方法,createInstance方法用来创建一个新的Axios实例。但这里奇怪的是,返回的示例并不是真正new出来的实例,而是一个幻影。实际在执行时,内部代码的指向还是内部的Axios对象。Axios内部使用了wrap来表示各个方法,可能真的是为了将真实的Axios实例隐藏。这么做作用在于防止外部修改内部的方法,做好了封装和防护。

function createInstance(defaultConfig) {var context = new Axios(defaultConfig);var instance = bind(Axios.prototype.request, context);// Copy axios.prototype to instanceutils.extend(instance, Axios.prototype, context);// Copy context to instanceutils.extend(instance, context);return instance;
}

不过,外部代码还是可以访问到内部的Axios实例的,在创建了幻影之后,继续执行以下代码:

// Expose Axios class to allow class inheritance
axios.Axios = Axios;// Factory for creating new instances
axios.create = function create(instanceConfig) {return createInstance(mergeConfig(axios.defaults, instanceConfig));
};// Expose Cancel & CancelToken
axios.Cancel = require('./cancel/Cancel');
axios.CancelToken = require('./cancel/CancelToken');
axios.isCancel = require('./cancel/isCancel');// Expose all/spread
axios.all = function all(promises) {return Promise.all(promises);
};axios.spread = require('./helpers/spread');module.exports = axios;// Allow use of default import syntax in TypeScript
module.exports.default = axios;

好,这里是外部的一些构造。其实我们拿到axios对象时就可以发起请求了。接下来我们通过一个使用示例来说明请求过程。以下是我们的request请求层示例:

// 使用示例,业务网络层request.js
const service = axios.create({baseURL: BASE_API, timeout: TIMEOUT 
});service.interceptors.request.use(config => {return config;},error => {Promise.reject(error);}
);service.interceptors.response.use(response => {return Promise.reject(response);},error => {return Promise.reject(error);}
);export default service;

假设我们的业务网络层是上面的用法,然后在具体的业务代码处通过get方法发起了一次业务请求:

axios.get('/get/server').then(function (response) {}).catch(function (err) {});

当业务请求代码发起时,具体执行的是lib/core/Axios.js中的request方法:

// lib/core/Axios.js
Axios.prototype.request = function request(config) {/*eslint no-param-reassign:0*/// Allow for axios('example/url'[, config]) a la fetch APIif (typeof config === 'string') {config = arguments[1] || {};config.url = arguments[0];} else {config = config || {};}config = mergeConfig(this.defaults, config);config.method = config.method ? config.method.toLowerCase() : 'get';// Hook up interceptors middlewarevar chain = [dispatchRequest, undefined];var promise = Promise.resolve(config);this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {// 向数组头部添加chain.unshift(interceptor.fulfilled, interceptor.rejected);});this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {// 向数组尾部添加chain.push(interceptor.fulfilled, interceptor.rejected);});while (chain.length) {promise = promise.then(chain.shift(), chain.shift());}return promise;
};

request方法的参数为一个config对象,而这个对象是由以下信息组成的:

{method: 'get',url: '/get/server'
}

紧接着会通过mergeConfig方法将自定义的config对象与默认的config对象进行合并:

// lib/core/Axios.jsconfig = mergeConfig(this.defaults, config);

而这里的this.defaults实际内部如下:

// lib/defaults.js
var defaults = {adapter: getDefaultAdapter(),// 默认的请求转换transformRequest: [function transformRequest(data, headers) {normalizeHeaderName(headers, 'Accept');normalizeHeaderName(headers, 'Content-Type');if (utils.isFormData(data) ||utils.isArrayBuffer(data) ||utils.isBuffer(data) ||utils.isStream(data) ||utils.isFile(data) ||utils.isBlob(data)) {return data;}if (utils.isArrayBufferView(data)) {return data.buffer;}if (utils.isURLSearchParams(data)) {setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');return data.toString();}if (utils.isObject(data)) {setContentTypeIfUnset(headers, 'application/json;charset=utf-8');return JSON.stringify(data);}return data;}],// 默认的相应转换,自定义转换方法,Json解析transformResponse: [function transformResponse(data) {/*eslint no-param-reassign:0*/if (typeof data === 'string') {try {data = JSON.parse(data);} catch (e) { /* Ignore */ }}return data;}],/*** A timeout in milliseconds to abort a request. If set to 0 (default) a* timeout is not created.*/timeout: 0,xsrfCookieName: 'XSRF-TOKEN',xsrfHeaderName: 'X-XSRF-TOKEN',maxContentLength: -1,validateStatus: function validateStatus(status) {return status >= 200 && status < 300;}
};

总之是一些待会会用到的默认配置。合并的机制是优先取自定义的配置,再取默认配置,组成一个新的合并对象。

request的方法继续向下,到了关键的地方:

// lib/core/Axios.js// Hook up interceptors middlewarevar chain = [dispatchRequest, undefined];var promise = Promise.resolve(config);this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {// 向数组头部添加chain.unshift(interceptor.fulfilled, interceptor.rejected);});this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {// 向数组尾部添加chain.push(interceptor.fulfilled, interceptor.rejected);});

由于咱们的业务网络层使用了interceptors.request.useinterceptors.response.use这样的字样,所以我们应该看看对应的use方法做了什么:

// lib/core/InterceptorManager.js
InterceptorManager.prototype.use = function use(fulfilled, rejected) {this.handlers.push({fulfilled: fulfilled,rejected: rejected});return this.handlers.length - 1;
};

而InterceptorManager的构造方法如下:

// lib/core/InterceptorManager.js
function InterceptorManager() {this.handlers = [];
}

InterceptorManager在构造之初内部只有一个数组属性handlers,所以当业务网络层使用use方法时,会将对应的fulfilled, rejected组成一个新的对象Push到这个数组中。所以再回来forEach的地方:

// lib/core/InterceptorManager.js
InterceptorManager.prototype.forEach = function forEach(fn) {utils.forEach(this.handlers, function forEachHandler(h) {if (h !== null) {fn(h);}});
};

forEach内部仅仅将handlers遍历,将数组中的对象通过forEach的回调方法传出,所以在Axios的request方法内,就是将业务网络层所定义的request interceptors与response interceptors压入数组chain中。所以在两个forEach执行完之后,数组chain的执行如下:

chain = [request.interceptors.success, request.interceptors.fail, dispatchRequest, undefined, response.interceptors.success, response.interceptors.fail]

然后就是根本性的一环:

// lib/core/Axios.jswhile (chain.length) {promise = promise.then(chain.shift(), chain.shift());}

当while方法执行时,开始触发chain中所塞进去的各个方法。在这里首先执行的是request.interceptors.success,也就是业务网络层所定义的请求拦截层。在我们的示例中什么处理都没做,于是再执行dispatchRequest。这个dispatchRequest可大有来头,是请求的核心:

// lib/core/dispatchRequest.js
function dispatchRequest(config) {throwIfCancellationRequested(config);// Support baseURL configif (config.baseURL && !isAbsoluteURL(config.url)) {config.url = combineURLs(config.baseURL, config.url);}// Ensure headers existconfig.headers = config.headers || {};// Transform request dataconfig.data = transformData(config.data,config.headers,config.transformRequest);// Flatten headersconfig.headers = utils.merge(config.headers.common || {},config.headers[config.method] || {},config.headers || {});// 为什么要删除Header中的请求方式?utils.forEach(['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],function cleanHeaderConfig(method) {delete config.headers[method];});var adapter = config.adapter || defaults.adapter;return adapter(config).then(function onAdapterResolution(response) {throwIfCancellationRequested(config);// Transform response data// 允许自定义转换方法response.data = transformData(response.data,response.headers,config.transformResponse);return response;}, function onAdapterRejection(reason) {if (!isCancel(reason)) {throwIfCancellationRequested(config);// Transform response dataif (reason && reason.response) {reason.response.data = transformData(reason.response.data,reason.response.headers,config.transformResponse);}}return Promise.reject(reason);});
};

dispatchRequest方法执行了以下事情:

  • 1.校验这次的请求是否已取消。
  • 2.构造完整的请求Url。
  • 3.确认header存在。
  • 4.转换请求数据与header。转换方法在这里也可以通过config自定义。默认转换为Json串。
  • 5.合并config.headers。
  • 6.删除config.headers中请求方法所对应的值。
  • 7.获取对应的网络请求适配器并发起请求。默认的adapter主要有两种:1.浏览器环境下为XMLHttpRequest. 2.Node环境下为https库或者http库,这里还支持自定义网路请求框架。

在这里代码分析我们假设运行环境为浏览器,那我们进入浏览器环境的dispatchRequest方法:

// lib/adapters/xhr.js
function xhrAdapter(config) {return new Promise(function dispatchXhrRequest(resolve, reject) {var requestData = config.data;var requestHeaders = config.headers;if (utils.isFormData(requestData)) {delete requestHeaders['Content-Type']; // Let the browser set it}var request = new XMLHttpRequest();// HTTP basic authenticationif (config.auth) {var username = config.auth.username || '';var password = config.auth.password || '';requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);}// 这里的method从哪来的?request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true);// Set the request timeout in MSrequest.timeout = config.timeout;// Listen for ready staterequest.onreadystatechange = function handleLoad() {if (!request || request.readyState !== 4) {return;}// The request errored out and we didn't get a response, this will be// handled by onerror instead// With one exception: request that using file: protocol, most browsers// will return status as 0 even though it's a successful requestif (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {return;}// Prepare the responsevar responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response;var response = {data: responseData,status: request.status,statusText: request.statusText,headers: responseHeaders,config: config,request: request};settle(resolve, reject, response);// Clean up requestrequest = null;};// Handle browser request cancellation (as opposed to a manual cancellation)request.onabort = function handleAbort() {if (!request) {return;}reject(createError('Request aborted', config, 'ECONNABORTED', request));// Clean up requestrequest = null;};// Handle low level network errorsrequest.onerror = function handleError() {// Real errors are hidden from us by the browser// onerror should only fire if it's a network errorreject(createError('Network Error', config, null, request));// Clean up requestrequest = null;};// Handle timeoutrequest.ontimeout = function handleTimeout() {reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED',request));// Clean up requestrequest = null;};// Add xsrf header// This is only done if running in a standard browser environment.// Specifically not if we're in a web worker, or react-native.if (utils.isStandardBrowserEnv()) {var cookies = require('./../helpers/cookies');// Add xsrf headervar xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ?cookies.read(config.xsrfCookieName) :undefined;if (xsrfValue) {requestHeaders[config.xsrfHeaderName] = xsrfValue;}}// Add headers to the requestif ('setRequestHeader' in request) {utils.forEach(requestHeaders, function setRequestHeader(val, key) {if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {// Remove Content-Type if data is undefineddelete requestHeaders[key];} else {// Otherwise add header to the requestrequest.setRequestHeader(key, val);}});}// Add withCredentials to request if neededif (config.withCredentials) {request.withCredentials = true;}// Add responseType to request if neededif (config.responseType) {try {request.responseType = config.responseType;} catch (e) {// Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.// But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.if (config.responseType !== 'json') {throw e;}}}// Handle progress if neededif (typeof config.onDownloadProgress === 'function') {request.addEventListener('progress', config.onDownloadProgress);}// Not all browsers support upload eventsif (typeof config.onUploadProgress === 'function' && request.upload) {request.upload.addEventListener('progress', config.onUploadProgress);}if (config.cancelToken) {// Handle cancellationconfig.cancelToken.promise.then(function onCanceled(cancel) {if (!request) {return;}request.abort();reject(cancel);// Clean up requestrequest = null;});}if (requestData === undefined) {requestData = null;}// Send the requestrequest.send(requestData);});
};

xhrAdapter方法为浏览器环境下的核心,主要做了以下事情:

  • 1.构造XMLHttpRequest对象。
  • 2.判断是否配置用户名密码,如果有,则添加到Header中。
  • 3.通过open方法打开请求。
  • 4.设置超时时间。
  • 5.配置onreadystatechange回调方法。
  • 6.配置onabort回调方法。
  • 7.配置onerror回调方法。
  • 8.配置ontimeout回调方法。
  • 9.如果是标准的浏览器环境,则添加xsrf值。
  • 10.如果要求withCredentials,则将withCredentials设为true。
  • 11.如果配置了responseType,则配置responseType。
  • 12.如果配置了下载回调方法,则添加下载回调方法。
  • 13.如果配置了上传回调方法,则添加上传回调方法。
  • 14.判断这时是否取消了请求,如果取消请求,则取消请求。
  • 15.发起请求。

可以看到,xhrAdapter内部很贴心的为我们做了各种适配和校验。发起请求后,如果网络执行正常,那么我们的关注点应该在onreadystatechange回调方法内:

// lib/adapters/xhr.js
request.onreadystatechange = function handleLoad() {if (!request || request.readyState !== 4) {return;}// The request errored out and we didn't get a response, this will be// handled by onerror instead// With one exception: request that using file: protocol, most browsers// will return status as 0 even though it's a successful requestif (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {return;}// Prepare the responsevar responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response;var response = {data: responseData,status: request.status,statusText: request.statusText,headers: responseHeaders,config: config,request: request};settle(resolve, reject, response);// Clean up requestrequest = null;};

onreadystatechange内部做了以下事情:

  • 1.对file:请求协议做特殊处理。
  • 2.构造响应对象。
  • 3.进入settle方法。
// lib/core/settle.js
module.exports = function settle(resolve, reject, response) {var validateStatus = response.config.validateStatus;if (!validateStatus || validateStatus(response.status)) {resolve(response);} else {reject(createError('Request failed with status code ' + response.status,response.config,null,response.request,response));}
};

settle内部允许自行判断可接收的状态,通过validateStatus方法校验。执行完这一部之后,就算执行完成了。

到此为止应该是执行刚刚xhrAdapter中所返回的Promise,我们需要回到这个Promise所对应的then方法:

// lib/core/dispatchRequest.jsreturn adapter(config).then(function onAdapterResolution(response) {throwIfCancellationRequested(config);// Transform response data// 允许自定义转换方法response.data = transformData(response.data,response.headers,config.transformResponse);return response;}, function onAdapterRejection(reason) {if (!isCancel(reason)) {throwIfCancellationRequested(config);// Transform response dataif (reason && reason.response) {reason.response.data = transformData(reason.response.data,reason.response.headers,config.transformResponse);}}return Promise.reject(reason);});

一切顺利,这里应该执行onAdapterResolution方法。onAdapterResolution方法内执行了以下事情:

  • 1.校验是否取消请求。
  • 2.对返回的对象做反序列化处理,这里同样支持自定义反序列化方法。
  • 3.返回反序列化后的对象。

到这里,我们应该又去哪里找对应的then方法呢?我们需要一层层返回。刚刚dispatchRequest方法是在lib/core/Axios.js中的request中调用的,所以这里的then方法应该还在这里。还记得之前在request中执行过的这段代码吗?

  while (chain.length) {promise = promise.then(chain.shift(), chain.shift());}

没错,由于之前chain中保存了业务网络层自定义的请求拦截器与响应拦截器,所以dispatchRequest方法会被Promise执行到业务网络层的响应拦截器中,我们在这里再贴一下业务网络层的响应拦截器:

service.interceptors.response.use(response => {return Promise.reject(response);},error => {return Promise.reject(error);}
);

嗯,我们还是什么都没处理,这里执行完,就开始触发我们的业务请求处的then方法了:

axios.get('/get/server').then(function (response) {}).catch(function (err) {});

当时我们的业务代码中什么都没写,如果通过控制台输出的话,就能看到最终的返回结果了。

到这里为止就是Axios的整个请求过程了,你是否清楚了呢?


通过阅读Axios源码,有以下总结:

  • Promise是其中的粘合剂,又做了协作的约定。
  • 面向对象的熟练使用。
  • 良好的代码规范,入参出参与分号、隔行、注释。
  • 良好的说明文档:https://www.npmjs.com/package/axios 。
  • 允许控制内部的更多细节,例如数据转换方式。

缺点:

  • 没有对高并发做处理。

前端中的其它源码分析文章:
Promise源码解析 https://sahadev.blog.csdn.net/article/details/90722543
深入解析Node.js setTimeout方法的执行过程 https://sahadev.blog.csdn.net/article/details/90703250
Vue源码探究笔记 https://sahadev.blog.csdn.net/article/details/87943168

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

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

相关文章

修改安装路径 pip 以及修改运行路径

持久化安装 如果需要进行持久化安装, 需要使用持久化路径, 如下方代码示例: !mkdir /home/aistudio/external-libraries !pip install beautifulsoup4 -t /home/aistudio/external-libraries同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: import s…

对比学习有多火?文本聚类都被刷爆了…

文 | 花小花Posy大家好&#xff0c;我是小花。对比学习的大火???? 越来越旺了&#xff0c;已然从CV蔓延到NLP了。今天给大家介绍的正是一篇将对比学习应用到文本聚类上的工作&#xff0c;NAACL21新鲜出炉的paper——《Supporting Clustering with Contrastive Learning》。…

论文浅尝 - WWW2020 | 生成多跳推理问题以改善机器阅读理解能力

论文笔记整理&#xff1a;谭亦鸣&#xff0c;东南大学博士生。来源&#xff1a;WWW 2020链接&#xff1a;https://dl.acm.org/doi/pdf/10.1145/3366423.3380114概述这篇论文关注的任务是&#xff1a;基于给定文本的“多跳问题生成”&#xff08;多关系问题&#xff09;。作者提…

记一次Vue框架升级

框架升级背景 公司目前业务迭代很快&#xff0c;且大部分的流量都在公众号上。然而我们公众号所使用的框架却是3年前的Vue 1.0.16。面对Vue这3年来带来的无数新特性&#xff0c;我们只能望洋兴叹&#xff1a;看得见&#xff0c;摸不着&#xff0c;因为升级这事看起来太难了。 …

谈谈NLP下一个主战场:万亿参数的预训练模型!

自从BERT诞生以来&#xff0c;各大互联网巨头之间就展开了预训练语言模型军备竞赛&#xff0c;XLNet、ERNIE、RoBERTa、T5、GPT-3....但当事情进展到号称自己是zero-shot learner的GPT-3时&#xff0c;批判的声音变得明显多了。这么大&#xff0c;能用吗&#xff1f;真的能做到…

交互式调试器

import pdb pdb.set_trace()

人物志 | 美团女技术总监任登君:不要给自己的人生设限

在我们美团技术团队超过6000名工程师中&#xff0c;有众多的女同学&#xff0c;她们是支撑中国领先的生活服务电子商务平台不可或缺的力量。3月8日女神节&#xff0c;我们专访了她们的代表——美团广告平台技术负责人任登君。登君也是我们团队里目前职位最高的女性技术Leader&a…

论文浅尝 - ISWC2020 | KnowlyBERT: 知识图谱结合语言模型补全图谱查询

论文笔记整理&#xff1a;胡楠&#xff0c;东南大学博士。来源&#xff1a;ISWC 2020动机像Wikidata这样的现代知识图已经捕获了数十亿个RDF三元组&#xff0c;但是它们仍然缺乏对大多数关系的良好覆盖。同时在NLP研究的最新进展表明&#xff0c;可以轻松地查询神经语言模型以获…

Webpack构建性能优化指南

本指南翻译自webpack官方性能指南文档&#xff1a;https://webpack.js.org/guides/build-performance/ 构建性能 本指南涵盖了对增进构建或编译性能的一些有效的提示。 General 以下提示对开发环境或者生产环境都有效。 Stay Up to Date 保持最新的webpack版本。我们总是在…

LeetCode 92. 反转链表 II(双指针)

1. 题目 反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。 说明: 1 ≤ m ≤ n ≤ 链表长度。 示例:输入: 1->2->3->4->5->NULL, m 2, n 4 输出: 1->4->3->2->5->NULL来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xf…

我对你的爱,是只为你而留的神经元

文 | 白鹡鸰有一个小轶专属神经元编 | 小轶有一个白鹡鸰专属神经元什么是苹果&#xff1f;红的&#xff1f;绿的&#xff1f;黄的&#xff1f;球状&#xff1f;斑点&#xff1f;香气&#xff1f;需要咬上一口才能确定&#xff1f;或者……其实我们在说某家技术公司&#xff1f;…

Android动态日志系统Holmes

背景 美团是全球领先的一站式生活服务平台&#xff0c;为6亿多消费者和超过450万优质商户提供连接线上线下的电子商务网络。美团的业务覆盖了超过200个丰富品类和2800个城区县网络&#xff0c;在餐饮、外卖、酒店旅游、丽人、家庭、休闲娱乐等领域具有领先的市场地位。平台大&a…

领域应用 | 知识图谱在小米的应用与探索

本文转载自公众号&#xff1a;DataFunTalk。分享嘉宾&#xff1a;彭力 小米编辑整理&#xff1a;马瑶出品平台&#xff1a;DataFunTalk导读&#xff1a;小米知识图谱于2017年创立&#xff0c;已支持公司了每天亿级的访问&#xff0c;已赋能小爱同学&#xff0c;小米有品、智能问…

前端应用开发架构图谱

个人整理的前端架构图谱&#xff0c;之后会根据这个图谱不断的完善内容。希望这个图谱可以对开发同学的知识脉络有个梳理的作用。 相关图谱文件已上传至Github&#xff1a;https://github.com/sahadev/front-end-architecture&#xff0c;后续将不定期更新。 2020年02月28日已…

丹琦女神新作:对比学习,简单到只需要Dropout两下

文 | 花小花Posy上周把 《对比学习有多火&#xff1f;文本聚类都被刷爆了...》分享到卖萌屋的群里后&#xff0c;遭到了群友们一波嫌弃安利。小伙伴们表示&#xff0c;插入替换的数据增强方式已经Out了&#xff0c;SimCSE才是现在的靓仔。snowfloating说&#xff1a;看完Danqi …

美团点评移动端基础日志库——Logan

背景 对于移动应用来说&#xff0c;日志库是必不可少的基础设施&#xff0c;美团点评集团旗下移动应用每天产生的众多种类的日志数据已经达到几十亿量级。为了解决日志模块普遍存在的效率、安全性、丢失日志等问题&#xff0c;Logan基础日志库应运而生。 现存问题 目前&#xf…

整理一波国外前端学习网站

国内的普通开发者对于掌握一门新的技术不知道从哪里下手&#xff0c;看哪些书。为了获得相关知识会关注各种公众号、购买各种视频课程来学习&#xff0c;但由于这些内容本身有碎片化的特点&#xff0c;效果往往不太理想。以至于付出了大量的时间到最后不能够形成系统化的知识。…

论文浅尝 - ACL2020 | Segmented Embedding of Knowledge Graphs

来源&#xff1a;ACL2020链接&#xff1a;https://arxiv.org/pdf/2005.00856.pdf摘要知识图谱的嵌入愈发变成AI的热点之一&#xff0c;对许多下游任务至关重要&#xff08;如个性化推荐、问答等&#xff09;同时&#xff0c;此模型强调两个关键特性&#xff1a;利用足够多的特征…

【论文翻译】HeteSim:异构网络中相关性度量的通用框架

原文链接&#xff1a;https://blog.csdn.net/Mrong1013967/article/details/115330139 HeteSim&#xff1a;异构网络中相关性度量的通用框架 摘要 相似性搜索是许多应用中的一个重要功能&#xff0c;它通常侧重于度量同一类型对象之间的相似性。然而&#xff0c;在许多场景中&a…

LeetCode 234. 回文链表(快慢指针+链表反转)

1. 题目 请判断一个链表是否为回文链表。 示例 1: 输入: 1->2 输出: false示例 2: 输入: 1->2->2->1 输出: true进阶&#xff1a; 你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题&#xff1f;来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&a…