TypeScript(TS)๋ก ๋ง์ด๊ทธ๋ ์ด์
ํ๋ ํ๋ก์ ํธ์ r => r.data
์๋ต ์ธํฐ์
ํฐ๊ฐ ์์ต๋๋ค. AxiosResponse
์ ํ์ด ์์๋์ง ์๋๋ค๊ณ TS์ ์๋ฆฌ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํฉ๋๊น? as Array<...
๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ ์๋ฅผ ์๋ํ์ง๋ง AxiosResponse
๋ฅผ Array
๋ก ์บ์คํ
ํ ์ ์๊ธฐ ๋๋ฌธ์ ์๋ํ์ง ์์ต๋๋ค(์: .length๊ฐ ์์).
๊ฐ์ฌ ํด์!
axios.request<T>(...args)
์คํ์ผ ์ ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋ฐฐ์ด์ ๋ง์ง๋ง ์๋ต ์ธํฐ์
ํฐ๋ ์์์ ์ผ๋ก (currentResponse: any) => T
์ ๊ฐ์ ์ธํฐํ์ด์ค๋ฅผ ๋ฐ๋ฆ
๋๋ค.
๋ฐ๋ผ์ data
๊ฐ ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ:
interface ServerResponse {
data: ServerData
}
interface ServerData {
foo: string
bar: number
}
๊ทธ๋ฌ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋งํ ์ ์์ต๋๋ค.
axios.request<ServerData>({
url: 'https://example.com/path/to/data',
transformResponse: (r: ServerResponse) => r.data
}).then((response) => {
// `response` is of type `AxiosResponse<ServerData>`
const { data } = response
// `data` is of type ServerData, correctly inferred
})
@zcei ooh ์ค์ ๋ก ์ด๊ฒ์ axios.interceptors.response.use
์ ๊ฐ์ ๊ธ๋ก๋ฒ ์ธํฐ์
ํฐ์์๋ ์๋ํ์ง ์์ต๋๋ค.
๋ด ์๊ฐ์๋ - ์ธํฐ์
ํฐ๋ ํ์ฌ ๋งค์ฐ "๋์จํ" ์ ํ( any
)์ด๋ฏ๋ก ์๋ต ์ธํฐ์
ํฐ๋ฅผ ์ฐ๊ฒฐํ๊ณ (r: any): any => r.data
(๊ธฐ๋ณธ์ ์ผ๋ก ์๊ฒฉํ์ง ์์ ๋ชจ๋์์๋ ์
๋ ฅ์ ์๋ตํฉ๋๋ค.
axios.request
๋ฅผ ํธ์ถํ๋ ์ง์ ์์๋ง ์ผ๋ฐ์ผ๋ก ๊ตฌ์ฑํ ์ ์์ผ๋ฉฐ, ๊ทธ๋ฌ๋ฉด data
์์ฑ์ ์ ํ์ผ๋ก ์ ๋ฌ๋ฉ๋๋ค.
(์ค์ ๋ก ์์ ์ฝ๋ ์ค๋ํซ์์ ์ค์๋ฅผ ํ์ต๋๋ค. data
๋ ์ค์ ๋ก AxiosResponse<ServerData>
์ด๊ณ ServerData
์ ํ์ $ .data
ํ๋๊ฐ ์์ต๋๋ค. - ์
๋ฐ์ดํธํ์ต๋๋ค)
@zcei ์๋ ํ์ธ์ ์ฃ์กํฉ๋๋ค๋ง ์ด๊ฒ์ ์ ์์ ์์๋ ์๋ํ์ง ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ๊ฐ์กฐํ๊ธฐ ์ํด ์ฝ๋ ์๋๋ฐ์ค๋ฅผ ๋ง๋ค์์ต๋๋ค.
๋์ผํ ๋ฌธ์ ๊ฐ ์๋ ์ธํฐ์ ํฐ๋ ๋ณธ์ง์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ์์ฝ๋ ์ ์์ต๋๋ค.
this.instance.interceptors.response.use(response => response.data);
๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ๋ฐํ ์ ํ
this.instance.post<string>(...);
AxiosPromise<string>
์ด๋ฉฐ, ๋ฐ์ดํฐ๊ฐ ๋ํ๋ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค.
์ด๊ฒ์ ์๋์ ์ ๋๋ค. ์ธํฐ์ ํฐ์์ ๋ฐ์ดํฐ๋ฅผ ๋ณํ ํด์ผ ํ์ง๋ง ์๋ต ํค๋ฅผ ํธ์ด์คํธ ํด์๋ ์ ๋ฉ๋๋ค.
๋๋ ๋น์ ์ด ๋ค์๊ณผ ๊ฐ์ ์๋ฒ ์๋ต์ ๊ฐ์ง ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ต๋๋ค.
{
"data": {
"foo": 42
}
}
response.data.data
์ค์ฒฉ์ ์์ ๊ณ ์ถ์์ต๋๋ค. ์ธํฐ์
ํฐ์์ response.data
๋ฅผ ๋ฐํํ๋ฉด ๋์ค์ response.data.data.foo
response.data.foo
๋ฅผ ํตํด ์ก์ธ์คํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ response.foo
์ก์ธ์ค๋ ์๋ํ์ง ์์ต๋๋ค. ์๋ต ์ฝ๋ ๋ฑ๊ณผ ๊ฐ์ ๋ค๋ฅธ ํญ๋ชฉ์ ์ถ์ ํ๋ "๋ฃจํธ" ์๋ต ์์ค์ด๊ธฐ ๋๋ฌธ์
๋๋ค.
์ฃ์กํ์ง๋ง ์ ์ด๋ ๊ธฐ๋ฅ์ ์ผ๋ก๋ ๊ทํ์ ์ ์ ์ ๋์ํ์ง ์์ต๋๋ค.
์ธํฐ์
ํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ ์์ฑ์ ํ์ง ์๊ณ ๋ค์์ ์ํํด์ผ ํฉ๋๋ค.
this.instance.post<string>(...).then(response => response.data);
this.instance.get<number>(...).then(response => response.data);
๋ด๊ฐ ์ ์ํ๋ _๋ชจ๋ _ ๋์ ์์. ๊ทธ ๋ชจ๋ ์ฝ๋ ๋ฐ๋ณต์ ์์ ์ ๋ฌด์์ ๋๊น?
then
๊ฐ ์๋ ์์ฒญ์ด ์ฑ๊ณตํ ๋๋ง๋ค ์๋ต ์ฝ๋ ๋ฑ์ ๋ํด์๋ ๋ณ๋ก ์ ๊ฒฝ ์ฐ์ง ์์ต๋๋ค. ๋๋ ๋ฌด์ธ๊ฐ๊ฐ ์๋ํ์ง ์๋ ๊ฒฝ์ฐ์๋ง ์๋ต ์ฝ๋์ ์ ๊ฒฝ์ ์ฐ๋ฉฐ, ์ด๊ฒ์ด ๋ฐ๋ก ์ค๋ฅ ์ฒ๋ฆฌ๊ธฐ๊ฐ ์๋ ์ด์ ์
๋๋ค. , ์ธํฐ์
ํฐ์ ํน์ ๋์ ๋ชจ๋์์.
this.instance.interceptors.response.use(response => {
// Everything went well, pass only relevant data through
return response.data;
}, error => {
// Something went wrong, figure out how to handle it here or in a `.catch` somewhere down the pipe
});
์์ฒญ์ด ์ฑ๊ณตํ ๋๋ง๋ค, ์ฆ then์ด ์๋ ๊ฒฝ์ฐ ์๋ต ์ฝ๋์ ๋ํด ๋ณ๋ก ์ ๊ฒฝ ์ฐ์ง ์์ต๋๋ค.
๊ธ์, ๋น์ ์ ๋ค๋ฅธ ์ ๋ณด์ ์ ๊ฒฝ ์ฐ์ง ์์ ์๋ ์์ง๋ง, ๋น์ ์ด ์ค์ง ๋ชธ์๋ง ์ ๊ฒฝ์ ์ฐ๋ HTTP ํด๋ผ์ด์ธํธ ๋ฅผ ์ฌ์ฉํ๋ ๋ชจ๋ ์ฌ๋์๊ฒ ์ ํํ๋ ๊ฒ์ ์ค์ ๋ก ํด๊ฒฐ์ฑ
์ด ์๋๋๋ค.
์ฑ๊ณต์ ์ธ ํธ์ถ์์๋ ์ํ ์ฝ๋ ๋ฐ ํค๋์ ๋ํ ํฉ๋ฒ์ ์ธ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์ถฉ๋ถํฉ๋๋ค. 204
vs 200
, ์๋ ์ ํ ํค๋ ํ์ธ, ์ถ๊ฐ ๋ฆฌ์์ค(ํ์ด์ง ๋งค๊น)์ ๋ํ Link
ํค๋ ์ถ์ถ ๋ฑ pp.
์ ๊ฒฝ ์ฐ์ง ์๋๋ค๋ฉด Axios๋ฅผ ๊ฐ์ธ๊ณ ๋ชจ๋ ๊ฒ์ ๋ฒ๋ฆฌ์ญ์์ค.
this.instance.request = <T>(...args) => {
return axios.request<T>(...args).then(({ data }) => data)
}
this.instance.request<string>({ method: 'post', ... }).then(data => { ... });
this.instance.request<number>({ method: 'get', ... }).then(data => { ... });
ํ๋์ ํ๋ก์ ํธ์์ ๋ด๊ฐ ํ๋ ๋ฐฉ์๋๋ก ๋ชจ๋ ์ฌ๋์ด ์ผ์ ํด์ผ ํ๋ค๋ ๊ฐ๋ ์ ์ด๋์ ์ป์๋์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์ ๋ ๋จ์ํ ๋ชจ๋ ์์ฒญ์ โโ๋ํด ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก ํด์ ํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๊ณ ๋ ธ๋ ฅ ์ค์ด๋ฉฐ ์ด ๋ฌธ์ ๊ฐ ์ ๋ณด๋ค ๋จผ์ ๋ฐ์ํ๋ค๋ ์ ์ ๊ฐ์ํ ๋ ์ด ๋ฌธ์ ๊ฐ ์๋ ์ ์ผํ ์ฌ๋์ ์๋๋๋ค.
์ธํฐ์
ํฐ๋ ์ด๋ฆ๊ณผ readme์ ์ค๋ช
(๋ชจ๋ ์๋ต์ ๋ํด ๋ฌด์ธ๊ฐ๋ฅผ ์ํ)์ผ๋ก ์ฌ๋ฐ๋ฅธ ์ฅ์๋ฅผ ์ข์ํฉ๋๋ค. 204
๋ 200
๋ฑ์ ์ฒ๋ฆฌํ ๋ค์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ๊ฒ๋ ์ธํฐ์
ํฐ์์ ์๋ฏธ๊ฐ ์์ต๋๋ค. ๊ทธ๋ฌ๋ฉด ํ ์ค์์์ ์ฒ๋ฆฌํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
์ ์๊ฐ์ ์ง๊ด์ ์ธ ์๋ฃจ์ ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ ๋ฐฉํฅ์ผ๋ก ๊ฐ์ง ์๋๋ก ์ธํฐ์ ํฐ์์ ์ํ๋ ๊ฒ์ ๋ฐํํ๋ ๊ฒ์ ๋๋ค.
๋ฐ์ดํฐ์ ์ผ๋ถ ํ๋๋ฅผ ๋ณํํ๋ ค๋ ๊ฒฝ์ฐ:
this.instance.interceptors.response.use(response => {
response.data.foo = JSON.parse(response.data.bar);
return response;
});
Axios์ ๋ฐ์ดํฐ๋ฅผ ํ๊ณ ์ถ๋ค๋ฉด:
this.instance.interceptors.response.use(response => response.data);
์ด๊ฒ์ ๊ฐ๋ฐ์์๊ฒ ๋ฌด์์ ํ ๊ฒ์ธ์ง์ ๋ํ ์ ํ๊ถ์ ๋จ๊ธธ ๊ฒ์ ๋๋ค. ์ ์๊ฐ์๋ ์ด๊ฒ์ด ๋งค์ฐ ๋ ๋จ์ ์ธ ์ธํฐ์ ํฐ๋ณด๋ค ๋ซ์ต๋๋ค. ๋ฌผ๋ก ๋์ํ์ง ์์ผ์ ๋ ๋ฉ๋๋ค.
๋น์ ์ "๋ชจ๋ ์ฝ๋ ๋ฐ๋ณต์ ์์ "์ ๋ํด ์ถ๋ก ํ๊ณ ์์๊ธฐ ๋๋ฌธ์ ์ ๋ณด๊ฐ ํ์ํ ์ด์ ๋ฅผ ์ค๋ช ํ๋ ค๊ณ ํ์ต๋๋ค.
์ธํฐ์
ํฐ๊ฐ ๊ณตํต ๊ตฌ์กฐ ์์ด ์ ์ฒด ์๋ต์ ๋ค์์ ์ ์๋ ๊ฒฝ์ฐ ์ธํฐ์
ํฐ์ ์๋ต์์ ์ ํ ์์ ์ ์ ์งํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ฐฉ๋ฒ์ ์ค์ ๋ก ์ฐพ์ ์ ์์ต๋๋ค. :/
์์ฒญ์ ๋ํ ์๋ต ์ ํ์ any
๊ฐ ๋์ด์ผ ํ๋ฉฐ ๊ฐ๋ฐ์๊ฐ ์ฌ๋ฐ๋ฅธ ์์
์ ์ํํ ์ ์๋๋ก ๋
ธ๋ ฅํด์ผ ํฉ๋๋ค.
๋์๊ฒ ๊ทธ๊ฒ์ ํ๋์ ์์ฑ์ ์ก์ธ์คํ๋ ๊ฒ๋ณด๋ค ํธ์ํ ํ์ดํ์ผ๋ก ์ธํด ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด ๊ฒ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค.
"80% ์ฌ์ฉ ์ฌ๋ก"์ ๋ํ ์ ํ ์์ ์ฑ์ ์ ์งํ๋ฉด์ ์ธํฐ์ ํฐ๊ฐ ๋ฃจํธ ์๋ต์ ๋ฎ์ด์ธ ์ ์๋๋ก ํ๋ PR์ ์๊ฐํด๋ผ ์ ์๋ค๋ฉด ๋ํ ๋์ ์์ด ๊ธฐ์ ๊ฒ์ ๋๋ค!
๋ฌธ์ ๋ ๋ด๊ฐ ๋ง๋ ์์ ๋ ๊ฐ์ง ์๊ฐ ๋ชจ๋ ์ด๋ฏธ ์ค๋ช ํ ๋๋ก ์๋ํ๋ค๋ ๊ฒ์ ๋๋ค. ๊ธฐ๋ฅ์ ์ผ๋ก๋ ์๋ชป๋ ์ ํ์ผ ๋ฟ์ ๋๋ค. ์ธํฐ์ ํฐ์์ (์์ ๋) ์๋ต์ด ์๋ ๋ค๋ฅธ ๊ฒ์ ๋ฐํํ๋ ๊ฒ์ด ์๋ชป๋ ๊ฒฝ์ฐ ๊ฑฐ๊ธฐ์์ ์์๋๋ ์ ํ์ ์ ๋ฐ์ดํธํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋จผ์ @Etheryte ์ ๊ฐ์ ์ผ์ ํ๊ณ ์๋ค๋ ์ฌ์ค์ด ํฅ๋ฏธ๋กญ์ต๋๋ค!
์ฐ๋ฆฌ ์ฑ์์ r => r.data
๋ ์ฒด์ธ์ ์ต์ข
์๋ต ์ธํฐ์
ํฐ์ด๋ฉฐ ์๋ก ๊ณ ์นจ ํ ํฐ ๋ฑ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ํ ์ฝ๋์ ์์กดํ๋ ๋ค๋ฅธ ๊ฒ๋ค์ ์ฌ์ฉํฉ๋๋ค. ์ ํ.
TS์์ ์ด ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์์ฉํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ ์๋ ์๋ค๋ ์ ์ ์ดํดํฉ๋๋ค. ๊ทธ๋ฌ๋ @zcei Axios API(์ธํฐ์ ํฐ)์ ๊ณต์ ๋ถ๋ถ์ ์ฌ์ฉํ๋ฏ๋ก ์ด๊ฒ์ด Axios๋ฅผ ์ฌ์ฉํ๋ ํฉ๋ฒ์ ์ธ ๋ฐฉ๋ฒ์ด๋ผ๋ ๊ฒ์ ๋ถ์ธํ ์ ์์ต๋๋ค.
๋! ํญ์ ์๋ชป๋ ์ฝ๋ ๐คฆโโ๏ธ๋ฅผ ๋ณด๊ณ ์์๋๋ฐ ์ธํฐ์
ํฐ๊ฐ ์๋๋ผ transformResponse
์น์
์ ์์์ต๋๋ค - ์ ๋ง ์ฃ์กํฉ๋๋ค!
๋ฐํ ์ ํ์ ๋ณ๊ฒฝํ๋ ์ธํฐ์ ํฐ๋ฅผ ์ค๋ช ํ๊ธฐ ์ํด ์ ๋ ฅ์ ์ด๋ป๊ฒ ์ ๋ฐ์ดํธํฉ๋๊น?
์๋ง๋ ์ด๋ฐ ๊ฒ?
interface AxiosInstance {
request<T = any, R = AxiosResponse<T>> (config: AxiosRequestConfig): Promise<R>;
}
๋ค์๊ณผ ๊ฐ์ด ๋ถ๋ฅผ ์ ์์ต๋๋ค.
axios.request<User, string>({
method: 'get',
url: '/user?id=12345'
})
.then((foo: string) => { // <-- you could leave out the type annotation here, it's inferred
console.log(foo)
})
๋ฐฉ๊ธ ๋ก์ปฌ์์ ์๋ํ๊ณ ์ํ๋ ์์
์ ์ํํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ ๋
์ ํจ๊ป PR์ ๋ฐ์ ๋ชจ๋ ๋ฐฉ๋ฒ์ ๋ํด ์
๋ฐ์ดํธํ ์ ์์ต๋๋ค.
@zcei ์ข๋ค์! ๋ฌผ๋ก AxiosResponse๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ํ๋ ๊ฒ์ 99%์ ๊ฒฝ์ฐ์ ์๋ฏธ๊ฐ ์์ต๋๋ค ๐
๋ฃ๊ธฐ ์ข์! ํผ์ ์ ๋๋ ค ๋ค์ ํ ๋ฒ ์ฃ์กํฉ๋๋ค ๐
@zcei ๋ฌธ์ ์์ต๋๋ค! Axios์ ์ถ์ ์ฃผ๊ธฐ๋ ๋ฌด์์ ๋๊น?
์์ต๋๋ค. ์์ง v1 ์ํ(#1333)์ ๋ํด ๋ณด๋ฅ ์ค์ธ ์ฌํญ์ด ์์ผ๋ฉฐ ๊ทธ ๋์ @nickuraltsev / @emilyemorehouse ๋ ํ์ํ ๋๋ง๋ค ๋ฆด๋ฆฌ์ค๋ฅผ ์ํํ๊ณ ์์ต๋๋ค.
v0.18
์ดํ๋ก ์ฝ๊ฐ์ ๊ฒฌ์ธ๋ ฅ์ด ์์ด(๋ด๊ฐ ๊ฐ์ฅ ์ข์ํ๋: ์ธ์คํด์ค์ ๋ํ ๋ฒ์ ์ง์ ์ต์
ํฌํจ) ๋ฆด๋ฆฌ์ค๋ฅผ ์ค๋จํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค. ๋ ๋ง์ ์ ๋ณด๋ฅผ ์ํ์๋ฉด Gitter ๋ก ์ฌ๋ฌ๋ถ์ ์ด๋ํด ๋๋ฆฌ๊ฒ ์ต๋๋ค.
0.19 ๋ฆด๋ฆฌ์ค๊ฐ ๋์ค๊ธธ ๋ฐ๋์ง๋ง ๋ง์ง๋ง์ผ๋ก ํ์ธํ ๊ฒฐ๊ณผ ๋ง์คํฐ๊ฐ CI์ ์คํจํ์ต๋๋ค. 1.0์ด ์ถ์๋๋ฉด ๋ ํ์คํ๊ณ ์ ๊ธฐ์ ์ธ ๋ฆด๋ฆฌ์ค ์ผ์ ์ ์ํฉ๋๋ค.
๊ฐ์ ๋ฌธ์ ๋ฅผ ๋ง๋๋ค. ํด๊ฒฐ์ฑ ์ด ์์ต๋๊น?
@qidaneix ๋ฆด๋ฆฌ์ค๊ฐ ๋์ฌ ๋๊น์ง npm install axios/axios#master
์ค์น๋ฅผ ์๋ํ ์ ์์ต๋๋ค. #1605๋ ๊ทธ๊ฒ์ ๊ณ ์ณค์ด์ผ ํ๋ค. ํ
์คํธ๋ฟ๋ง ์๋๋ผ ์ค์ ์ฌ์ฉ ์ฌ๋ก์ ์ค์ ๋ก ๋์์ด ๋๋์ง ์ฌ๋ถ์ ๋ํ ํผ๋๋ฐฑ์ ๋ฐ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๐
@zcei ๋ด์ผ ํด๋ด์ผ์ง
@zcei ์ธ์ ์ถ์๋๋์ง ์ฌ์ญค๋ด๋ ๋ ๊น์?
1.0.0์ด ์ถ์๋ ๋ +1?
์ด๊ฒ์ ํ์คํ pre-1.0 ๋ฆด๋ฆฌ์ค๊ฐ ๋ ๊ฒ์ ๋๋ค. @Khaledgarbaya Matt๊ฐ NPM์๋ ์ถ๊ฐํ์ต๋๊น? ๊ทธ๋ ์ง ์์ผ๋ฉด ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ๋ฆด๋ฆฌ์คํ๋ ๋๋จธ์ง ์ ์ง ๊ด๋ฆฌ์์๊ฒ ์น์ ํด์ผ ํฉ๋๋ค ๐
๋ชจ๋ ์๋ . ํ์ฌ NPM ๋ฆด๋ฆฌ์ค๋ฅผ ๊ด๋ฆฌํ๊ณ ์์ต๋๋ค. ๋ค๋ฅธ 1.0.0 ์ด์ ๋ฆด๋ฆฌ์ค๋ฅผ ๋ฐํํ๊ณ ์ถ์ง๋ง Travis ํ ์คํธ๊ฐ ์คํจํ๊ณ ์์ผ๋ฉฐ ์์ง ์์ ํ ๊ธฐํ๊ฐ ์์์ต๋๋ค. ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋๋ฉด ์ฆ์ ๋ฐฐํฌํ ์ ์์ด ๋์ฑ ๊ธฐ์ฉ๋๋ค ๐ฌ
@zcei npm ์ ์ฅ์์ ์ถ๊ฐ๋์ง ์์์ผ๋ฉฐ ๋ณ๊ฒฝ ์ฌํญ์ ๋ณํฉํ ์๋ง ์์ต๋๋ค.
์ด ๋ฌธ์ ์ ๋ํ ์ ๋ฐ์ดํธ๊ฐ ์์ต๋๊น? ๊ฐ๊น์ด ์ฅ๋์ 2๊ฐ์์ฐจ์ ๊ฐ์ ๋ฆด๋ฆฌ์ค๊ฐ ์์ต๋๊น?
+1
โค๏ธ ์ง๊ธ ์ถ์๋๋ค๋ฉด
์๊ณ ์์ง๋ง ํ์ฌ ์ฐจ๋จ๋์ด ์์ต๋๋ค. ๐ ์ฌ๊ธฐ์์ ๋ ๋ง์ ์ ๋ณด๋ฅผ ์ป์ ์ ์์ต๋๋ค: https://github.com/axios/axios/issues/1657#issuecomment -410766031
0.19.0-beta.1์ ์ผ๋ถ๋ก ์ถ์๋์์ต๋๋ค.
npm install [email protected]
๋๋ npm install axios@next
๋ฅผ ์ฌ์ฉํ์ฌ ์ค์นํ ์ ์์ต๋๋ค.
์๋ง๋ ์ด๋ฐ ๊ฒ?
interface AxiosInstance { request<T = any, R = AxiosResponse<T>> (config: AxiosRequestConfig): Promise<R>; }
๋ค์๊ณผ ๊ฐ์ด ๋ถ๋ฅผ ์ ์์ต๋๋ค.
axios.request<User, string>({ method: 'get', url: '/user?id=12345' }) .then((foo: string) => { // <-- you could leave out the type annotation here, it's inferred console.log(foo) })
๋ฐฉ๊ธ ๋ก์ปฌ์์ ์๋ํ๊ณ ์ํ๋ ์์ ์ ์ํํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ ๋ ์ ํจ๊ป PR์ ๋ฐ์ ๋ชจ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ ๋ฐ์ดํธํ ์ ์์ต๋๋ค.
User(T, ์ฒซ ๋ฒ์งธ ์ผ๋ฐ ๋งค๊ฐ๋ณ์)๊ฐ ์ฌ์ฉ๋์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ฌ์ฉ์ ์ ์ ๋ฐํ ์ ํ์ ์ฌ์ฉํ๋ ค๋ ๊ฒฝ์ฐ ์ด์ํ๊ฒ ๋ณด์ ๋๋ค ๐
axios.request<void, string>({
...
})
void๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋ช ํํ ์ ์์ต๋๋ค.
@emilyemorehouse ๊ฐ์ฌํ์ง ์๊ฒ ๋ค๋ฆฌ์ง๋ง 0.19-๋ฒ ํ๊ฐ 3๊ฐ์ ๋์ ๊ณต๊ฐ๋์์ต๋๋ค. GA ๋ฆด๋ฆฌ์ค์ ๋ํ ETA๊ฐ ์์ต๋๊น? ์ฐ๋ฆฌ ํ๋ก์ ํธ์๋ ์ด๋ฌํ ์์ ์ฌํญ ์ค ํ๋๊ฐ ํ์ํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๋๋ Gitter ์ฑ๋์์ ์ด๊ฒ์ ๋ฌผ์์ง๋ง ์ ์ง ๋ณด์๊ฐ ๊ฑฐ๊ธฐ์์ ์๋ตํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค ...
๋ฆด๋ฆฌ์ค ์ ์ ํด๊ฒฐํด์ผ ํ๋ ๋ฌธ์ ๋ ๋ฌด์์ด๋ฉฐ ์ถ์ ํ ์ ์๋ ์ฅ์๊ฐ ์๋ค๋ ๊ฒ์ด ๋ ๋์ ํํ์ผ ๊ฒ์ ๋๋ค. ๋ง์ ๊ด์ฌ์ด ์๋ ๊ฒ ๊ฐ์ผ๋ ์์ ์ ๋ถ์ฐํ๊ณ ํ์ํ ์์ ์ ๋ช ํํ๊ฒ ์ดํดํ๋ฉด ์์ ์๋๋ฅผ ๋์ด๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
์ด๋ฏธ 0.19์ ๋ํ ํ๋ก์ ํธ ๋ง์ผ์คํค์ด ์์ง๋ง ๋์ด๋ ํฐ์ผ์ ๋ช ๋ฌ ๋์ ๋ณ๊ฒฝ ์ฌํญ์ด ์์ต๋๋ค.
const func1: ๋ชจ๋ = () => { axios.request(...) ๋ฐํ }
๋ด axios.d.ts
AxiosResponse
์ฌ์ ์:
import axios from 'axios'
declare module 'axios' {
export interface AxiosResponse<T = any> extends Promise<T> {}
}
์ด ๋ฌธ์ ๋ฅผ ๋ฒํ๊ณ ์์ต๋๋ค. ๊ทธ๊ฒ์ ์๋ํฉ๋๋ค ... ๋ฐฉ๊ธ AxiosInstance ์ ์๋ฅผ ๋ก์ปฌ ํ์ดํ์ ๋ณต์ฌํ์ ๋ ์์์ง ๋ง ๊ตฌํ ๋ ์๋ฃจ์
์ ๋ด ์๊ฐ์ ๋งค์ฐ ์ฅํฉํฉ๋๋ค. (Typescript ์ ๋ฌธ๊ฐ๊ฐ ์๋) ์๋ชป๋ ์ผ์ํ์ง ์๋ ํ. axios.create
๋ก ์์ฑ๋ ๋ณ๋์ axios ์ธ์คํด์ค๋ฅผ ์ฌ์ฉํ๊ณ ์ด ์ธํฐ์
ํฐ๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์:
AxiosClient.interceptors.response.use(
response => response && response.data,
error => error && error.response && error.response.data
);
์ฌ๊ธฐ์ response.data
๋ ํญ์ ๋ค์ ํ์์ ๊ฐ์ต๋๋ค.
export interface APIResponse<T = any> {
data: T;
message: string;
status: boolean;
}
๋ค์๊ณผ ๊ฐ์ด AxiosClient.post
๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
AxiosClient.post<EndpointAPIResponse, APIResponse<EndpointAPIResponse>>('/endpoint', { someData });
.then
์ ์ ์ ํ ์ ํ์ ๊ฐ์ต๋๋ค. ๋ด๊ฐ ์ฌ๊ธฐ์์ ๋ญ๊ฐ ์๋ชปํ๊ณ ์์ต๋๊น, ์๋๋ฉด ์ ๋ง ์ฅํฉํด์ผํฉ๋๊น? ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ์ธ์คํด์ค๋ฅผ ์์ฑํ ๋ ์์๋๋ ์๋ต ์คํค๋ง๋ฅผ ์ ๋ฌํ ์ ์๋ค๋ฉด ํจ์ฌ ์ข์ ๊ฒ์
๋๋ค. ํ์ง๋ง ์๋ํ๊ฒ ๋ง๋ค ์๋ ์์ต๋๋ค.
export interface AxiosInstance<R> {
<T = any>(config: AxiosRequestConfig): Promise<R<T>>;
<T = any>(url: string, config?: AxiosRequestConfig): Promise<R<T>>;
defaults: AxiosRequestConfig;
interceptors: {
request: AxiosInterceptorManager<AxiosRequestConfig>;
response: AxiosInterceptorManager<R>;
};
getUri(config?: AxiosRequestConfig): string;
request<T = any>(config: AxiosRequestConfig): Promise<R<T>>;
get<T = any>(url: string, config?: AxiosRequestConfig): Promise<R<T>>;
delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<R<T>>;
head<T = any>(url: string, config?: AxiosRequestConfig): Promise<R<T>>;
post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R<T>>;
put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R<T>>;
patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R<T>>;
}
export interface AxiosStatic extends AxiosInstance<AxiosResponse> {
create<T = AxiosResponse>(config?: AxiosRequestConfig): AxiosInstance<T>;
Cancel: CancelStatic;
CancelToken: CancelTokenStatic;
isCancel(value: any): boolean;
all<T>(values: (T | Promise<T>)[]): Promise<T[]>;
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
}
์ ๋ค๋ฆญ ์ ํ์ด ์๋ axios.create()
๋๋ axios
์์๋ ์ ์๋ํ์ง๋ง ๋ค์๊ณผ ๊ฐ์ด ์ธํฐํ์ด์ค๋ฅผ ์ ๋ฌํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ฉ๋๋ค.
const AxiosClient = axios.create<APIResponse>({
// ...
});
๊ทธ๋ฐ ๋ค์ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํฉ๋๋ค. AxiosClient.post<string>('/endpoint').then(value => value.data)
, value.data
has type... T. ๊ฒ๋ค๊ฐ ์์ ๋ฒ์ ์ ์ค์ ๋ก node_modules์์ ์ด๋ฌํ ํ์ดํ์ ๊ต์ฒดํ๋ ๊ฒฝ์ฐ์๋ง ์๋ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์์ ํ ๋ค์์ด๊ณ ์ ๋ ์ด์ฒด์ ์ธ ์ฌ๋์ผ๋ก ๋๋ฉ๋๋ค. ๋๊ตฌ๋ ์ง ์ด๊ฒ์ผ๋ก ๋๋ฅผ ๋์ธ ์ ์์ต๋๊น?
ํธ์ง: ์๊ฒ ์ต๋๋ค. ๊ทธ๋ฐ ์์ผ๋ก ์ ๋ค๋ฆญ์ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ์๋ํ์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค(R์ด ์ ๋ค๋ฆญ ์ ํ์ผ ๋ R<T>
๋ ์ฌ๋ฐ๋ฅธ ๊ตฌ๋ฌธ์ด ์๋์ง๋ง ์ด๋ค ์ด์ ๋ก WebStorm์ด ๊ฐ์กฐ ํ์๋์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๊ฒ์ ๋๋ฅผ ์ํด); https://github.com/Microsoft/TypeScript/issues/1213 ์ด๊ฒ์ด ํด๊ฒฐ๋ ๊ฒ์ด๋ผ๊ณ ๊ฐ์ ํ์ง๋ง ๊ตฌํ๋๋์ง ์ฌ๋ถ๋ ์ ์ ์์ต๋๋ค.
const request = <T>(options: AxiosRequestConfig) => {
return axios.request<IResponse<T>>(options).then<T>(response => {
const data = response.data;
if (data.c !== '0') {
return Promise.reject(new Error(data.m || 'error'));
}
return data.d;
});
}
์ฌ์ฉ:
request<IApiGetBrandGoodsInfoByIds>({
method: 'GET',
url: '/api/a/b',
});
@zcei ์์ง ํด๊ฒฐ๋์ง ์์๋์? ๋ค์ ์์ ์ ์ํํ ์ ์์ต๋๋ค.
// so I created an axios instance:
const instance = axios.create(someOptions);
// then used interceptors
instance.interceptors.response.use((res) => res.data.data); // server response will always have 'data'
// then when using the following to make a request
instance.get<string>(someURI); // suppose server response was {data: 'some message'}
// ^^ the above returns type AxiosPromise<string>. How do I get it to return type Promise<string> instead?
๊ฐ์ ๋ฌธ์ ๊ฐ ์์ด์ ๋ฒ์ 0.19beta๋ฅผ ์ค์นํ์ต๋๋ค. ๋ํ ์ฌ๋ฐ๋ฅธ ์ ํ์ ๊ตฌ๋ฌธ ๋ถ์ํ ์ ์์ต๋๋ค.
๋ด
axios.d.ts
AxiosResponse
์ฌ์ ์:import axios from 'axios' declare module 'axios' { export interface AxiosResponse<T = any> extends Promise<T> {} }
์ค ๋์ฐํผ
์ ๋ ์ธํฐ์
ํฐ๋ฅผ ์ฌ์ฉํ์ฌ response => response.data
์ ๊ฐ์ ์์
์ ์ํํฉ๋๋ค. ๋ฐ๋ผ์ AxiosResponse
๋ํผ๋ฅผ ์์ ํ ์ ๊ฑฐํด์ผ ํฉ๋๋ค.
๋๋ ๋ง์นจ๋ด ๋ค์๊ณผ ๊ฐ์ด ๋๋ฉ๋๋ค.
import axios from 'axios'
declare module 'axios' {
export interface AxiosInstance {
request<T = any> (config: AxiosRequestConfig): Promise<T>;
get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
head<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
}
}
์ฌ์ฉ ๋ฐฉ๋ฒ์ ๋ชจ๋ฅด๋ ์ฌ๋์ด ์๋ ๊ฒฝ์ฐ:
{
"compilerOptions": {
"typeRoots": [
"./node_modules/@types",
"./src/types/",
]
}
}
์ด๊ฒ์ ๋๋ฅผ ์ํด ์๋ํฉ๋๋ค.
Api.boards.createBoard = jest.fn((name:string) => {
const mockBoardResult = {
created_on: mockBoardData.date,
name,
threads: [],
updated_on: mockBoardData.date,
_id: mockBoardData._id
};
return Promise.resolve({data:mockBoardResult}) as Promise<AxiosResponse<any>>
});
์ฌ์ ์ํ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ
import * as axios from 'axios'
declare module 'axios' {
interface AxiosInstance {
(config: AxiosRequestConfig): Promise<any>
}
}
์ธํฐ์
ํฐ ๋ฅผ ์ฌ์ฉํ ๋ AxiosResponse
์ ์์ฑ์ ์ถ๊ฐํด์๋ ์ ๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ธํฐ์
ํฐ๋ฅผ ๊บผ๋ผ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
// @axios-exts/add-foo-to-resp
declare module 'axios' {
interface AxiosResponse<T = any> {
foo: string
}
}
const addFooToResp = (res: AxiosResponse) => {
res.foo = 'bar'
return res
}
export default addFooToResp
// Your Project
import axios from 'axios'
import addFooToResp from '@axios-exts/add-foo-to-resp'
var id = axios.interceptors.response.use(addFooToResp)
axios.get('xx').then(res => {
// have type defined
// because we use `declare module 'axios'` ts can infer type
console.log(res.foo)
})
// but if then eject?
axios.interceptors.response.eject(id)
axios.get('xx').then(res => {
// also have type defined, it's maybe not reasonable
console.log(res.foo)
})
์ฐ๋ฆฌ๋ ์ typescript๋ฅผ ์ฌ์ฉํฉ๋๊น? ์ฐ๋ฆฌ ํ๋ก์ ํธ๊ฐ ์์ ํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
์ธ์ ๊ฐ ์ฐ๋ฆฌ๊ฐ ๊ธฐ๋ณธ ์ ํธ๋ฆฌํฐ์์ ์์ฑ์ ์ ๊ฑฐํ๋ค๋ฉด, ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ์ฐธ์กฐํ๋ ์ฝ๋๊ฐ ์ปดํ์ผ ํ์์ ์ค๋ฅ๋ฅผ ์์ฑํ๊ธฐ๋ฅผ ์ํ ๊ฒ์
๋๋ค.
๊ทธ๋์ ์ฐ๋ฆฌ๋ ์ธํฐ์
ํฐ ๋ฅผ ์ฌ์ฉํ์ฌ AxiosResponse
์ ์์ฑ์ ์ถ๊ฐํ๊ณ ์ ํ ์ ์ถ๋ฅผ ๊ฐ๊ณ ์ถ์ต๋๋ค. ์ด๋ ์ธํฐ์
ํฐ๊ฐ ๊บผ์ง ๋ ์ ํ ์ ์ถ๋ฅผ ์
๋ฐ์ดํธํ ์ ์๋์ง ํ์ธํ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์ ๋ชจ์๋ฉ๋๋ค.
axios๊ฐ ์ฌ์ฉ์์๊ฒ ๋ค์๊ณผ ๊ฐ์ด ์๋ ค์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
์ธํฐ์
ํฐ๋ AxiosResponse
์ ์ํฅ์ ์ฃผ์ง ์๋ ๊ฒ์ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค. AxiosResponse
์์ฑ์ ํ์ฅํ๊ณ ์ ํ ์ถ๋ก ์ ์ฌ์ฉํ๋ ค๋ฉด 'ํ๋ฌ๊ทธ์ธ'์ ์ข์ํด์ผ ํฉ๋๋ค.
// @axios-exts/add-foo-to-resp
declare module 'axios' {
interface AxiosResponse<T = any> {
foo: string
}
}
const addFooToResp = (res: AxiosResponse) => {
res.foo = 'bar'
return res
}
export default (axios) => {
axios.interceptors.response.use(addFooToResp)
}
// Your Project
import axios from 'axios'
import addFooToResp from '@axios-exts/add-foo-to-resp'
addFooToResp(axios)
100% ์์ ์ ์๋์ง๋ง ๊ทธ๋ฅ axios.interceptors.response.use
์ฌ์ฉํ๋๊ฒ๋ณด๋ค ์์ ํฉ๋๋ค
๊ทธ๋ฆฌ๊ณ ์ ๋ axios desgin ํ๋ฌ๊ทธ์ธ ์์คํ ์ ์ถ์ฒํฉ๋๋ค. ์ด์ ์ฐ๋ฆฌ๋ ํญ์ ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ ๋๋ค.
import axios from 'axios'
import wrapper from 'axios-cache-plugin'
let http = wrapper(axios, {
maxCacheSize: 15
})
export default http
wrapper
์ ๊ฐ์ด ํ๋ฌ๊ทธ์ธ์ axios์ ์ฐ๊ฒฐํ๋ ๋ฐ ์ฌ์ฉํฉ๋๋ค. ๋ชจ๋ ํ๋ฌ๊ทธ์ธ์๋ ๊ณตํต ๊ท์น์ด ์์ผ๋ฉฐ ์ถฉ๋ถํ ์ฐ์ํ์ง ์์ต๋๋ค. ๋๋ ์ข์ํด์ผํ๋ค๊ณ ์๊ฐํ๋ค
import axios from 'axios'
import axiosCache from 'axios-cache-plugin'
axios.use(axiosCache, {
// some options
})
export axios
// axios-cache-plugin
export default (axios) => {}
// or
export default {
install(axios){}
}
// like Vue.use for Vue.js
axios.request<T>(...args)
์คํ์ผ ์ ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋ฐฐ์ด์ ๋ง์ง๋ง ์๋ต ์ธํฐ์ ํฐ๋ ์์์ ์ผ๋ก(currentResponse: any) => T
์ ๊ฐ์ ์ธํฐํ์ด์ค๋ฅผ ๋ฐ๋ฆ ๋๋ค.๋ฐ๋ผ์
data
๊ฐ ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ:interface ServerResponse { data: ServerData } interface ServerData { foo: string bar: number }
๊ทธ๋ฌ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋งํ ์ ์์ต๋๋ค.
axios.request<ServerData>({ url: 'https://example.com/path/to/data', transformResponse: (r: ServerResponse) => r.data }).then((response) => { // `response` is of type `AxiosResponse<ServerData>` const { data } = response // `data` is of type ServerData, correctly inferred })
Pls๋ tsx๋ฅผ ์ฌ์ฉํ์ฌ Axios ์์ฒญ์ ํค๋ ๋ฐ ๊ตฌ์ฑ์ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ ์๋ ค์ค ์ ์์ต๋๊น?
@MoZiadAlhafez
declare module 'axios' {
interface AxiosRequestConfig {
useCache: boolean
}
}
๊ทธ๋ฌ๋ ์ด๊ฒ์ ๊ถ์ฅ๋์ง ์์ต๋๋ค
๊ธด ์ด์ผ๊ธฐ์ง๋ง #1605์์ ํด๊ฒฐ๋ ๊ฒ ๊ฐ์ต๋๋ค. https://github.com/axios/axios/issues/1510#issuecomment -396894600์ ์ฐธ์กฐํ์ธ์.
๋ด๊ฐ ๋ญ๊ฐ๋ฅผ ์๋ชป ์ดํดํ๋ค๋ฉด ์ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ์ฌ ์ ๋ฌธ์ ๋ฅผ ์ฌ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊ฐ์ฌ ํด์.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๋ด
axios.d.ts
AxiosResponse
์ฌ์ ์: