我正在创建一个 Web 应用程序,以 django Rest 框架作为后端,以 React 作为前端。我从 create-react-app 生成的 react 应用程序。为了进行 api 调用,我使用 fetch Api。我发现我的 api 调用中有一些重复,需要重构。但我知道哪种模式更好。
这是代码:
API.js
let _options = {headers: new Headers({'Content-Type': 'application/json'})}
const _url = {
'users': '/api/users/',
'obtain-token': '/api/obtain-token/',
'verify-token': '/api/verify-token/',
'refresh-token': '/api/refresh-token/'
}
const _fetch = (request) => {
return fetch(request)
.then(res => {
if ( ! res.ok) {
let err = {
'status': res.status,
'statusText': res.statusText,
'data': {}
}
return res.json().then(
data => {
err.data = data
return Promise.reject(new Error(JSON.stringify(err)))
},
() => Promise.reject(new Error(JSON.stringify(err)))
)
}
return res.json()
})
.catch(err => {
return Promise.reject(err)
})
}
export const obtainToken = (username, password) => {
const credential = {username, password}
let options = _options
options.method = 'POST'
options.body = JSON.stringify(credential)
const request = new Request(_url['obtain-token'], options)
return _fetch(request)
}
export const verifyToken = (token) => {
let options = _options
options.method = 'POST'
options.body = JSON.stringify({token})
const request = new Request(_url['verify-token'], options)
return _fetch(request)
}
export const refreshToken = (token) => {
let options = _options
options.method = 'POST'
options.body = JSON.stringify({token})
const request = new Request(_url['refresh-token'], options)
return _fetch(request)
}
export const getUser = (username, token='') => {
let options = _options
options.method = 'GET'
if (token) options.headers.append('Authorization', `JWT ${token}`)
const request = new Request(`${_url['users']}/${username}`, options)
return _fetch(request)
}
我喜欢这段代码的是,当我需要请求资源时,我只需运行一个带有所需参数的函数,而不知道它是 get 或 post 或其他,并且我不需要传递 header 配置和 url。
// example api call
let token = '4346h9r7yt47t9...'
verifyToken(token)
.then(data => {
// server response json available here
token = data.token
})
.catch(err => {
// handle network error and bad response here
console.log(err)
})
我正在关注@challenger 解决方案。并设法缩短它:
// Change _build function name to makeRequest and export it
const makeRequest = (name, _url='', body=undefined, headers={}) => {
let [method, url] = source[name]
let options = {
headers: new Headers({
'Content-Type': 'application/json',
...headers,
})
}
options.method = method
if (body) options.body = JSON.stringify(body)
return _fetch(url+_url, options)
}
export default makeRequest
但是,当然要调用此函数,我需要提供附加的 url 以及自定义 header (如果需要)。但随着这个项目的进展,事实证明附加的 url(由用户详细资源使用)和 Costum header (由需要身份验证的资源使用)是需要的。
最佳答案
let source = {
'getUser': (..._p) => ['GET', `/api/users/${_p[0]}`, undefined, {'Authorization': `JWT ${_p[1]}`}],
'obtainToken': (..._p) => ['POST','/api/obtain-token/', {username:_p[0], password:_p[1]}],
'verifyToken': (..._p) => ['POST','/api/verify-token/', {token:_p[0]}],
'refreshToken': (..._p) => ['POST', '/api/refresh-token/',{token:_p[0]}]
}
const requests = {}
Object.keys(source).forEach(key => {
requests[key] = (...params) => {
let [method, url, body, headers ={}] = source[key](...params)
let options = {
headers: new Headers({
'Content-Type': 'application/json',
...headers,
})
}
options.method = method
if (body) options.body = JSON.stringify(body)
return _fetch(new Request(url, options))
}
})
export default requests
它需要更多的测试和审查..
关于javascript - 需要深入了解如何构建 javascript fetch API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47302342/