Leider haben wir aktuell keine teufel.de Gutscheine oder Angebote verfügbar. Wenn Sie den Gutschein-Alarm aktivieren informieren wir Sie sobald wir neue Gutscheine oder Angebote finden.


Einfach den Code beim Bestellen angeben Der Rabatt wird dann automatisch abgezogen
Gutschein anzeigen





Gilt auf nicht rabattierte Artikel
140 Euro Mindestbestellwert

Einfach den Code beim Bestellen angeben Der Rabatt wird dann automatisch abgezogen
Gilt nur für Neukunden.


Gilt auf das gesamte Angebot Nicht kombinierbar mit anderen Aktionsgutscheinen. Gilt nur für Privatkunden. Eine Barauszahlung ist nicht möglich.

Gilt auf Versandkosten # 1. 前言 在上一篇文章中,我们分析了axios的拦截器原理,知道了拦截器是用Promise和Array原型上的方法unshift和push实现的。那么接下来,我们就分析axios的核心:请求发送器dispatchRequest。 # 2. 示例 在分析之前,我们先看一个发送请求的示例: javascript axios({ method: "post", url: "/api/base/post", data: { a: 1, b: 2, }, }); 从上面的示例中,我们可以看到,在调用axios的时候,我们传入了一个配置对象config,在该配置对象中我们设置了请求方法method、请求URL地址、请求体data等等。那么,axios内部是如何根据我们传入的这些配置来发送请求的呢?接下来,我们就深入源码一探究竟。 # 3. 源码分析 我们首先找到dispatchRequest函数的定义所在文件lib/core/dispatchRequest.js。 ## 3.1 函数定义 在该文件中,我们可以找到dispatchRequest函数的定义,如下: javascript function dispatchRequest(config) { throwIfCancellationRequested(config); // 确保headers存在 config.headers = config.headers || {}; // 转换请求数据 config.data = transformData( config.data, config.headers, config.transformRequest ); // 压平headers config.headers = utils.merge( config.headers.common || {}, config.headers[config.method] || {}, config.headers ); 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); // 转换响应数据 response.data = transformData( response.data, response.headers, config.transformResponse ); return response; }, function onAdapterRejection(reason) { if (!isCancel(reason)) { throwIfCancellationRequested(config); // 转换响应数据 if (reason && reason.response) { reason.response.data = transformData( reason.response.data, reason.response.headers, config.transformResponse ); } } return Promise.reject(reason); } ); } 从函数定义中我们可以看到,该函数内部主要做了四件事: 1. 判断请求是否已经被取消,如果已经被取消,则抛出异常; 2. 确保请求头headers存在; 3. 转换请求数据; 4. 使用请求发送器adapter发送请求,并返回Promise对象; 接下来,我们就对这四件事逐一进行分析。 ## 3.2 判断请求是否已经被取消 首先,第一件事就是判断请求是否已经被取消,调用了throwIfCancellationRequested函数,该函数定义如下: javascript function throwIfCancellationRequested(config) { if (config.cancelToken) { config.cancelToken.throwIfRequested(); } } 该函数内部判断了如果配置对象config上存在取消令牌cancelToken,那么就调用该取消令牌的throwIfRequested方法,如果该请求已经被取消,那么该方法内部就会抛出异常,并且该异常会被上抛到请求拦截器或响应拦截器的rejected函数中,关于取消请求这块后续会单独分析。 ## 3.3 确保请求头 headers 存在 第二件事就是确保请求头headers存在,如果不存在,就将其设置为空对象{}。 javascript config.headers = config.headers || {}; ## 3.4 转换请求数据 第三件事就是转换请求数据,调用了transformData函数,该函数定义如下: javascript function transformData(data, headers, fns) { utils.forEach(fns, function transform(fn) { data = fn(data, headers); }); return data; } 该函数接收三个参数: - data:需要转换的数据; - headers:请求头; - fns:转换函数数组; 该函数内部遍历转换函数数组fns,将每一个转换函数的返回值作为下一个转换函数的输入,最后返回转换后的数据。 那么,转换函数数组fns是从哪来的呢?从调用transformData函数时传入的第三个参数config.transformRequest可以看出,fns就是config.transformRequest,也就是我们传入的配置对象config中的transformRequest属性。 那么,transformRequest属性又是什么呢?其实,transformRequest属性是一个数组,数组里面是一个或多个转换函数,这些转换函数的作用是在发送请求之前对请求数据进行转换。我们可以通过axios的默认配置和mergeConfig函数找到它的默认值。 在lib/defaults.js文件中,我们可以找到transformRequest的默认值: javascript var defaults = { // ... 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)) { setContentTypeIfNotSet( headers, "application/x-www-form-urlencoded;charset=utf-8" ); return data.toString(); } if (utils.isObject(data)) { setContentTypeIfNotSet(headers, "application/json;charset=utf-8"); return JSON.stringify(data); } return data; }, ], // ... }; 从代码中可以看到,transformRequest的默认值是一个数组,数组里面有一个转换函数transformRequest,该函数内部主要做了以下几件事: 1. 规范化请求头中的Accept和Content-Type字段; 2. 判断请求数据data的类型,如果是FormData、ArrayBuffer、Buffer、Stream、File、Blob等类型,则直接返回data; 3. 如果data是ArrayBuffer的视图,则返回视图对应的ArrayBuffer对象; 4. 如果data是URLSearchParams类型,则设置请求头Content-Type为application/x-www-form-urlencoded;charset=utf-8,并返回data的字符串形式; 5. 如果data是普通对象,则设置请求头Content-Type为application/json;charset=utf-8,并返回data的JSON字符串形式; 6. 如果data是其他类型,则直接返回data。 OK,接下来我们再回到dispatchRequest函数中,当我们调用transformData函数转换完请求数据后,接下来又对请求头headers做了一些处理,如下: javascript // 压平headers config.headers = utils.merge( config.headers.common || {}, config.headers[config.method] || {}, config.headers ); utils.forEach( ["delete", "get", "head", "post", "put", "patch", "common"], function cleanHeaderConfig(method) { delete config.headers[method]; } ); 首先,使用utils.merge方法将config.headers.common、config.headers[config.method]和config.headers合并成一个新的对象,并赋值给config.headers。这样做的目的是将config.headers中的common和config.method对应的属性合并到config.headers中,并且config.headers中的属性会覆盖common和config.method对应的属性。 然后,使用utils.forEach方法遍历["delete", "get", "head", "post", "put", "patch", "common"]数组,将config.headers中的这些属性删除。这样做的目的是删除config.headers中不需要的属性,只保留真正的请求头信息。 ## 3.5 使用请求发送器 adapter 发送请求 第四件事就是使用请求发送器adapter发送请求,并返回Promise对象。代码如下: javascript var adapter = config.adapter || defaults.adapter; return adapter(config).then( function onAdapterResolution(response) { throwIfCancellationRequested(config); // 转换响应数据 response.data = transformData( response.data, response.headers, config.transformResponse ); return response; }, function onAdapterRejection(reason) { if (!isCancel(reason)) { throwIfCancellationRequested(config); // 转换响应数据 if (reason && reason.response) { reason.response.data = transformData( reason.response.data, reason.response.headers, config.transformResponse ); } } return Promise.reject(reason); } ); 首先,从配置对象config中获取adapter,如果config.adapter不存在,则使用默认的adapter,即defaults.adapter。 然后,调用adapter函数,传入配置对象config,并返回一个Promise对象。 接着,在Promise对象的then方法中,分别定义了onAdapterResolution和onAdapterRejection两个函数,分别处理请求成功和请求失败的情况。 在onAdapterResolution函数中,首先判断请求是否已经被取消,如果已经被取消,则抛出异常;然后转换响应数据,最后返回响应对象。 在onAdapterRejection函数中,首先判断请求是否已经被取消,如果已经被取消,则抛出异常;然后判断如果reason存在并且reason.response存在,则转换响应数据,最后返回一个被拒绝的Promise对象。 那么,adapter到底是什么呢?其实,adapter是一个函数,它的作用是根据当前环境(浏览器或 Node.js)来发送请求。在lib/defaults.js文件中,我们可以找到adapter的默认值: javascript function getDefaultAdapter() { var adapter; if (typeof XMLHttpRequest !== "undefined") { // 浏览器环境 adapter = require("./adapters/xhr"); } else if ( typeof process !== "undefined" && Object.prototype.toString.call(process) === "[object process]" ) { // Node.js环境 adapter = require("./adapters/http"); } return adapter; } var defaults = { // ... adapter: getDefaultAdapter(), // ... }; 从代码中可以看到,adapter的默认值是通过getDefaultAdapter函数获取的,该函数内部判断了当前环境,如果是浏览器环境,则使用xhr适配器;如果是 Node.js 环境,则使用http适配器。 关于xhr适配器和http适配器的具体实现,我们会在后续的文章中详细分析。 # 4. 总结 本篇文章我们分析了axios的核心:请求发送器dispatchRequest。我们知道了dispatchRequest函数内部主要做了四件事: 1. 判断请求是否已经被取消,如果已经被取消,则抛出异常; 2. 确保请求头headers存在; 3. 转换请求数据; 4. 使用请求发送器adapter发送请求,并返回Promise对象; 并且,我们还知道了adapter是一个函数,它的作用是根据当前环境(浏览器或 Node.js)来发送请求。 OK,dispatchRequest函数我们就分析到这,下篇文章我们将会分析axios的取消请求功能,敬请期待。

Gilt auf Versand Nicht mit anderen Aktionsgutscheinen kombinierbar. Nur für Privatkunden. Keine Barauszahlung. Weiterverkauf untersagt.

Gilt auf Versandkosten

Gilt für Privatkunden Nicht kombinierbar mit anderen Gutscheinen.
Wir schicken dir eine E-Mail, wenn es einen neuen
teufel.de Gutscheincode gibt!
teufel.de bietet folgende Zahlmöglichkeiten an: PayPal, MasterCard (Kreditkarte), Sofort Überweisung by Klarna, Clickandbuy, Vorauskasse, per Nachnahme (Zahlung bei Übergabe der Ware). Bei Zahlungen per PayPal hat man in vielen Fällen zudem die Möglichkeit neben der Zahlung mit dem PayPal Guthaben auch mittels SEPA Lastschrift von einem hinterlegten Konto oder Kreditkarte zu zahlen.Eventuell sind nicht alle Zahlmöglichkeiten für alle Dienstleistungen oder Produkte vorhanden. Mehr Informationen hierzu erhalten Sie während dem Bestellvorgang.