javascript - 需要深入了解如何构建 javascript fetch API

标签 javascript rest api design-patterns refactoring

我正在创建一个 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/

相关文章:

javascript - 使用 selenium 和 Python 单击 'onclick' 按钮

javascript - 修改 mouseEvent 对象的 `target` 以进行事件委托(delegate)

java - 为第 3 方 REST API 创建 Apache Camel 组件?

javascript - 如何等待获取json文件的数据然后继续

javascript - 如何将 Sinon.JS spy 函数指定为类定义的一部分?

javascript - <ion-scroll Zooming ="true">-标签似乎不允许在模态对话框中缩放

java - 通过我自己的 RESTful API 路由 API 调用是否被视为可接受的策略?

android - 如何将 JSON 响应转换为字符串并显示在屏幕上?

javascript - React js控制componentDidUpdate()方法

json - 如何修改返回JSON