繁体   English   中英

需要了解如何构建javascript提取API

[英]Need insight on how to build javascript fetch API

我正在创建一个将Django rest框架作为后端的Web应用程序,并作为前端进行响应。 我从create-react-app生成的react应用程序。 要进行api调用,我使用访存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,否则我不需要传递标头配置和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)
  })

我正在关注@挑战者解决方案。 并设法使它变得更短:

// 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,以及如果需要的话提供一个自定义标头。 但是随着该项目的进行,事实证明需要附加的url(由用户详细信息资源使用)和costum标头(由需要身份验证的资源使用)。

let source = {
  'getUser': ['GET', '/api/users/'],
  'obtain-token': ['POST','/api/obtain-token/'],
  'verify-token': ['POST','/api/verify-token/'],
  'refresh-token':['POST', '/api/refresh-token/']
}

let _build = (name, _url, body, 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 new Request(url+_url, options)
}

接着

export const obtainToken = (username, password) => {
  const credential = {username, password}
  const request = _build('obtainToken','', credential, {})
  return _fetch(request)
}
export const verifyToken = (token) => {
  const request = _build('verifyToken', '',{token}, {})
  return _fetch(request)
}

export const refreshToken = (token) => {
  const request = _build('refreshToken', '', {token}, {})
  return _fetch(request)
}
export const getUser = (username, token='') => {
  let headers = {'Authorization': `JWT ${token}`}

  const request = _build('getUser',`/${username}`, undefined, headers)
  return _fetch(request)
}

甚至更多,而不是...

return new Request(url+_url, options)

在_build函数中,您可以将其替换为

return _fetch(new Request(url+_url, options))

这使您可以拥有:

   export const obtainToken = (username, password) => {
      const credential = {username, password}
      return _build('obtainToken','', credential, {})
    }
    export const verifyToken = (token) => {
      return _build('verifyToken', '',{token}, {})
    }

    export const refreshToken = (token) => {
      retun _build('refreshToken', '', {token}, {})
    }

    export const getUser = (username, token='') => {
      let headers = {'Authorization': `JWT ${token}`}
      return _build('getUser',`/${username}`, undefined, headers)
    }
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

它需要更多的测试和审查。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM