Aktuelle PicturePeople Gutscheine & Deals

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

Diese Gutscheine könnten dir auch gefallen

Skinfox Sportwear Logo
Gültig bis 30. Januar 2031

10€ – EXTRA Rabatt beim Kauf einen Skinfox Boards

Saisonaction 2020 - 10 € EXTRA Have FUN to earn together

XXX2020 Gutschein anzeigen
AfB Logo
Gültig bis 14. August 2039

10% Rabatt auf PCs

Die meisten Firmen tauschen ihre PCs nach wenigen Jahre aus. Doch diese gebrauchten Computer sind meistens noch voll funktionsfähig. AfB hat es sich zum Auftrag gemacht diese Computer zu günstigen Preisen zu verkaufen. IT-Hardware erschwinglich für Jedermann – egal ob mittelständischer Unternehmer oder für den Privatgebrauch, im breiten Sortiment der AfB-Computer wird bestimmt jeder fündig. Der Gutschein kann mehrmals pro Kunde eingelöst werden, ist zeitlich unbegrenzt und ohne Mindestbestellwert gültig. Hinweis: Gutscheincodes sind nicht einlösbar auf bereits reduzierte Ware, Aktions-Produkte, LiveShopping Angebote, Neuware und Zubehör. Gutscheincodes sind nicht kombinierbar mit anderen Gutscheinen, Rabatten oder Partnercodes.

XXXcs10 Gutschein anzeigen
Konsolenkost Logo
Gültig bis 31. Juli 3031

10,00€ Rabatt

Einfach den Code beim Bestellen angeben Der Rabatt wird dann automatisch abgezogen
80 Euro Mindestbestellwert

XX0521 Gutschein anzeigen
ModeStern Logo
Gültig bis 31. Dezember 2026

25,00 Prozent Rabatt


39 Euro Mindestbestellwert

EM25 Gutschein anzeigen
Superestudio Logo
Gültig bis auf Widerruf

35€ Rabatt


250 Euro Mindestbestellwert

XXXXXXNT35 Gutschein anzeigen
HIFI Components Logo
Gültig bis auf Widerruf

10 Prozent Rabatt

Gilt auf alle Marantz-Produkte Einfach den Code beim Bestellen angeben Der Rabatt wird dann automatisch abgezogen

XXXXXX2017 Gutschein anzeigen
ParfumGroup Logo
Gültig bis 10. April 2030

4,00€ Rabatt

XXXXXXXX-AF4 Gutschein anzeigen
lieblingsfoto.de Logo
Gültig bis 18. Juni 2034

61,00 Prozent Rabatt

Gilt auf Foto auf Aluminium Einfach den Code beim Bestellen angeben Der Rabatt wird dann automatisch abgezogen

XCA61 Gutschein anzeigen
myboshi.net Logo
Gültig bis 31. Dezember 2026

10,00 Prozent Rabatt

Einfach den Code beim Bestellen angeben Der Rabatt wird dann automatisch abgezogen
30 Euro Mindestbestellwert

XXXXU295 Gutschein anzeigen
CHEEX Logo
Gültig bis 10. Juli 2026

7 Tage gratis

Gilt im jährlichen Abo Einfach den Code beim Bestellen angeben Der Rabatt wird dann automatisch abgezogen

XEVEN Gutschein anzeigen

Abgelaufene PicturePeople Gutscheine & Deals

Abgelaufen
CHEEX Logo
abgelaufen am: 31.10.25

Gratis Mini-Shooting

Abgelaufen
CHEEX Logo
abgelaufen am: 31.10.25

Gratis Mini-Shooting

# 1. 前言 在上一篇文章中,我们实现了axios的请求和响应拦截器功能,并且为它们编写了对应的测试用例。接下来,我们就来实现axios的配置化,所谓配置化是指:我们希望能够对每次请求的配置进行设定,设定一些公共的默认配置,并且还可以在每次请求中自定义配置,并且自定义配置优先级高于默认配置。 # 2. 需求分析 我们希望axios可以有默认配置,并且还可以在每次请求中传入自定义配置,自定义配置可以覆盖默认配置,并且希望默认配置和自定义配置可以合并。如下: typescript // 默认配置 axios.defaults.headers.common["test"] = 1; axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; // 自定义配置 const instance = axios.create({ headers: { test: 2, }, }); instance.get("/more/get", { headers: { test: 3, }, }); 对于headers这类复杂对象属性,我们需要进行深拷贝,同时也处理了其它一些情况,如下: typescript axios.defaults.baseURL = "https://api.example.com"; // 默认配置 axios.defaults.headers.common["test"] = 1; // 自定义配置 const instance = axios.create({ baseURL: "https://img.example.com", headers: { test: 2, }, }); instance.get("/more/get", { headers: { test: 3, }, }); 合并后的配置应该是: json { "baseURL": "https://img.example.com", "headers": { "common": { "test": 1 }, "test": 3 } } # 3. 默认配置 首先,我们先来实现默认配置。默认配置我们可以在src/axios.ts中定义,如下: typescript // src/axios.ts const defaults: AxiosRequestConfig = { timeout: 0, headers: { common: { Accept: "application/json, text/plain, */*", }, }, }; const methodsNoData = ["delete", "get", "head", "options"]; methodsNoData.forEach((method) => { defaults.headers[method] = {}; }); const methodsWithData = ["post", "put", "patch"]; methodsWithData.forEach((method) => { defaults.headers[method] = { "Content-Type": "application/x-www-form-urlencoded", }; }); 我们定义了defaults常量,它包含默认配置。对于headers,我们定义了common和一些请求方法的headers,common表示对于任何类型的请求都要添加该header,而对于get、post等方法,也会添加对应的header,但是会覆盖common中相同的header。 # 4. 合并策略 合并策略我们采用与axios官方相同的策略,如下: typescript // src/core/mergeConfig.ts import { AxiosRequestConfig } from "./types"; import { deepMerge, isPlainObject } from "./util"; const strats = Object.create(null); function defaultStrat(val1: any, val2: any): any { return typeof val2 !== "undefined" ? val2 : val1; } function fromVal2Strat(val1: any, val2: any): any { if (typeof val2 !== "undefined") { return val2; } } function deepMergeStrat(val1: any, val2: any): any { if (isPlainObject(val2)) { return deepMerge(val1, val2); } else if (typeof val2 !== "undefined") { return val2; } else if (isPlainObject(val1)) { return deepMerge(val1); } else if (typeof val1 !== "undefined") { return val1; } } const stratKeysFromVal2 = ["url", "params", "data"]; stratKeysFromVal2.forEach((key) => { strats[key] = fromVal2Strat; }); const stratKeysDeepMerge = ["headers"]; stratKeysDeepMerge.forEach((key) => { strats[key] = deepMergeStrat; }); export default function mergeConfig( config1: AxiosRequestConfig, config2?: AxiosRequestConfig ): AxiosRequestConfig { if (!config2) { config2 = {}; } const config = Object.create(null); for (let key in config2) { mergeField(key); } for (let key in config1) { if (!config2[key]) { mergeField(key); } } function mergeField(key: string): void { const strat = strats[key] || defaultStrat; config[key] = strat(config1[key], config2![key]); } return config; } 合并规则如下: - 对于url、params、data这些属性,默认使用config2中的配置,即自定义配置。 - 对于headers这类复杂对象,采用深拷贝的方式,并且会合并config1和config2中的配置。 - 对于其他属性,采用默认策略,即如果config2中有配置,则使用config2中的配置,否则使用config1中的配置。 # 5. 修改 axios 函数 接下来,我们需要修改src/axios.ts中的axios函数,让它支持默认配置和自定义配置的合并。 typescript // src/axios.ts import { AxiosRequestConfig, AxiosPromise, Method } from "./types"; import dispatchRequest from "./core/dispatchRequest"; import InterceptorManager from "./core/InterceptorManager"; import mergeConfig from "./core/mergeConfig"; interface Interceptors { request: InterceptorManager; response: InterceptorManager; } interface PromiseChain { resolved: InterceptorResolved | ((config: AxiosRequestConfig) => AxiosPromise); rejected?: InterceptorRejected; } export default class Axios { defaults: AxiosRequestConfig; interceptors: Interceptors; constructor(initConfig: AxiosRequestConfig) { this.defaults = initConfig; this.interceptors = { request: new InterceptorManager(), response: new InterceptorManager(), }; } request(url: any, config?: any): AxiosPromise { if (typeof url === "string") { if (!config) { config = {}; } config.url = url; } else { config = url; } config = mergeConfig(this.defaults, config); const chain: PromiseChain[] = [ { resolved: dispatchRequest, rejected: undefined, }, ]; this.interceptors.request.forEach((interceptor) => { chain.unshift(interceptor); }); this.interceptors.response.forEach((interceptor) => { chain.push(interceptor); }); let promise = Promise.resolve(config); while (chain.length) { const { resolved, rejected } = chain.shift()!; promise = promise.then(resolved, rejected); } return promise; } get(url: string, config?: AxiosRequestConfig): AxiosPromise { return this._requestMethodWithoutData("get", url, config); } delete(url: string, config?: AxiosRequestConfig): AxiosPromise { return this._requestMethodWithoutData("delete", url, config); } head(url: string, config?: AxiosRequestConfig): AxiosPromise { return this._requestMethodWithoutData("head", url, config); } options(url: string, config?: AxiosRequestConfig): AxiosPromise { return this._requestMethodWithoutData("options", url, config); } post(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise { return this._requestMethodWithData("post", url, data, config); } put(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise { return this._requestMethodWithData("put", url, data, config); } patch(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise { return this._requestMethodWithData("patch", url, data, config); } _requestMethodWithoutData(method: Method, url: string, config?: AxiosRequestConfig) { return this.request( Object.assign(config || {}, { method, url, }) ); } _requestMethodWithData(method: Method, url: string, data?: any, config?: AxiosRequestConfig) { return this.request( Object.assign(config || {}, { method, url, data, }) ); } } 我们修改了Axios类,在构造函数中传入默认配置,并且在request方法中,我们使用mergeConfig函数合并默认配置和自定义配置。 # 6. 修改默认配置 接下来,我们需要修改src/axios.ts中的默认配置,并且导出axios实例。 typescript // src/axios.ts const defaults: AxiosRequestConfig = { timeout: 0, headers: { common: { Accept: "application/json, text/plain, */*", }, }, }; const methodsNoData = ["delete", "get", "head", "options"]; methodsNoData.forEach((method) => { defaults.headers[method] = {}; }); const methodsWithData = ["post", "put", "patch"]; methodsWithData.forEach((method) => { defaults.headers[method] = { "Content-Type": "application/x-www-form-urlencoded", }; }); const axios = new Axios(defaults); export default axios; # 7. 修改 create 函数 我们还需要修改src/axios.ts中的create函数,让它支持创建新的axios实例。 typescript // src/axios.ts export function createInstance(config: AxiosRequestConfig): AxiosStatic { const context = new Axios(config); const instance = Axios.prototype.request.bind(context); extend(instance, context); return instance as AxiosStatic; } const axios = createInstance(defaults); axios.create = function create(config) { return createInstance(mergeConfig(defaults, config)); }; export default axios; # 8. 编写测试用例 接下来,我们编写测试用例来测试我们的配置合并功能。 typescript // test/config.spec.ts import axios from "../src/index"; import mergeConfig from "../src/core/mergeConfig"; describe("config", () => { it("should merge config", () => { const config1 = { url: "config1", data: { foo: "bar", }, }; const config2 = { url: "config2", params: { bar: "foo", }, }; const merged = mergeConfig(config1, config2); expect(merged.url).toBe("config2"); expect(merged.data).toEqual({ foo: "bar" }); expect(merged.params).toEqual({ bar: "foo" }); }); it("should merge config with headers", () => { const config1 = { headers: { common: { Accept: "application/json, text/plain, */*", }, get: { "X-Requested-With": "XMLHttpRequest", }, }, }; const config2 = { headers: { common: { "X-Test": "test", }, post: { "X-Test2": "test2", }, }, }; const merged = mergeConfig(config1, config2); expect(merged.headers.common).toEqual({ Accept: "application/json, text/plain, */*", "X-Test": "test", }); expect(merged.headers.get).toEqual({ "X-Requested-With": "XMLHttpRequest", }); expect(merged.headers.post).toEqual({ "X-Test2": "test2", }); }); it("should merge config with deep properties", () => { const config1 = { auth: { username: "foo", password: "bar", }, }; const config2 = { auth: { username: "baz", }, }; const merged = mergeConfig(config1, config2); expect(merged.auth).toEqual({ username: "baz", password: "bar", }); }); it("should merge config with undefined", () => { const config1 = { timeout: 1000, }; const config2 = { timeout: undefined, }; const merged = mergeConfig(config1, config2); expect(merged.timeout).toBe(1000); }); it("should merge config with null", () => { const config1 = { timeout: 1000, }; const config2 = { timeout: null, }; const merged = mergeConfig(config1, config2); expect(merged.timeout).toBeNull(); }); }); # 9. 总结 至此,我们就实现了axios的配置化功能,并且编写了对应的测试用例。在下一篇文章中,我们将实现axios的取消功能。

Abgelaufen
CHEEX Logo
abgelaufen am: 11.05.25

Muttertag-Special

Gilt für Fotoshootings Nicht kombinierbar mit anderen Aktionen. Keine Barauszahlung.

Abgelaufen
CHEEX Logo
abgelaufen am: 30.04.25

25,00€ Rabatt

Gilt beim Ferien-Special auf ein Mini-Fotoshooting für Kinder & Familien Folgt unserem Link, um das Angebot kennenzulernen. Weitere Infos auf der Aktionsseite. Einen Gutscheincode benötigt ihr nicht.

Abgelaufen
CHEEX Logo
abgelaufen am: 21.04.25

100,00€ Rabatt

Gilt beim Oster-Special auf ein Professionelles Fotoshooting mit Bilderpaket Folgt unserem Link, um das Angebot kennenzulernen. Weitere Infos auf der Aktionsseite. Einen Gutscheincode benötigt ihr nicht.

Gutschein Alarm

Wir schicken dir eine E-Mail, wenn es einen neuen
PicturePeople Gutscheincode gibt!

*

Mit der Eintragung deiner E-Mail Adresse akzeptierst du unsere Datenschutzbestimmungen. Geschützt durch reCaptcha Datenschutzerklärung - Nutzungsbedingungen