Skip to content

Instantly share code, notes, and snippets.

@heisian
Last active November 20, 2019 17:27
Show Gist options
  • Select an option

  • Save heisian/fdd5b42e35e98c906488eca0193f21c9 to your computer and use it in GitHub Desktop.

Select an option

Save heisian/fdd5b42e35e98c906488eca0193f21c9 to your computer and use it in GitHub Desktop.
FYSTSXHR
import Xhr from 'Xhr'
const xhr = new Xhr()
// Or alternatively, xhr is just functional:
// import xhr from 'xhr'
// Assume xhr instance (or functional equivalent) is being passed in
;(async (xhr) => {
// Current API
let response = await xhr('patch')
.user(2)
.identity(2)
.data({
email: 'tim@getethos.com',
password: 'somethignReally.Good!',
nameFirst: 'Timothy',
nameLast: 'Huang',
birthDate: '1985-10-21',
gender: 'Male',
})
.fetch()
// Hypothetical API, closure/DI-style
response = await xhr.patch((request) => {
request.path.user(2).identity(2)
request.headers({ 'Content-Type': 'application/json' })
request.data({
email: 'tim@getethos.com',
password: 'somethignReally.Good!',
nameFirst: 'Timothy',
nameLast: 'Huang',
birthDate: '1985-10-21',
gender: 'Male',
})
})
// Hypothetical again, using destructuring
response = await xhr.patch(({ path, headers, data }) => {
path.user(2).identity(2)
headers({ 'Content-Type': 'application/json' })
data({
email: 'tim@getethos.com',
password: 'somethignReally.Good!',
nameFirst: 'Timothy',
nameLast: 'Huang',
birthDate: '1985-10-21',
gender: 'Male',
})
})
// Hypothetical again, with custom path and query params
response = await xhr.get(({ path, params, headers, data }) => {
path('/some/custom/path')
params({
some: 'data',
will: 'getQueryStringified',
})
})
})
@roblevintennis
Copy link
Copy Markdown

roblevintennis commented Nov 20, 2019

Calling patch feels off xhr.patch as patch usually means some sort of update to an existing thing in my experience.

response = await xhr.patch((request) => {} implies to me that the internals is going to call this back with a request param that is used by consumer to set these properties, and then Xhr will use that to set things up internally and then execute the fetch; but why not then just have these passed in directly by client and do the same?

For the last custom path and query params one, I first read the { path, params, headers, data } inputs as properties, but they're actually methods the consumer uses to inject the values back to Xhr. Again, I think just letting the consumer do it and pass in is more straight forward.

I do like the idea of having convenience methods based on HTTP verb. It's familiar based on old jQuery days, and I think we could share same GET vs. POST interface as setting up xhr directly.

Here's my take on going all in on DI:

/*
interface XhrConfig {
  baseUrl?: string, /* internall will have a sensible default */
  httpMethod: HttpMethodType,
  requestOptions: XhrOptions = {}
  pathBuilder: PathBuilder,
  requestBody?: string, /* only for POST/PUT etc. */
}
*/

function Xhr({ baseUrl, method, path, requestBody }: XhrConfig) {...}
export Xhr

import Xhr from 'Xhr'
import pathBuilder from 'PathBuilder'

const xhr = new Xhr()

// GET
function termPolicyXhr(userId, identityId, termPolicyId) {
  return (method): Promise<XhrResponse> {
    // You still have the nice chaining for PathBuilder
    const path = new pathBuilder() 
      .user(userId)
      .identity(identityId)
      .termPolicy(termPolicyId)

    // Xhr calls fetch internally
    return xhr(/* baseUrl--optional, maybe has a default */, method, path, /* requestBody not meaningful here */) 
  }
}

// POST
function termPolicyCreateXhr(userId, identityId, termPolicyId, requestBody) {
  return (method): Promise<XhrResponse> {
    // You still have the nice chaining for PathBuilder
    const path = new pathBuilder() 
      .user(userId)
      .identity(identityId)
      .termPolicy(termPolicyId)

    // Xhr calls fetch internally
    return xhr(myBaseUrlOverride, method, path, requestBody) 
  }
}

@heisian
Copy link
Copy Markdown
Author

heisian commented Nov 20, 2019

how would I invoke termPolicyCreateXhr in this example?

perhaps,

import Xhr from 'xhr'
import termPolicyCreateXhr from 'termPolicyCreateXhr'

const xhrInstance = new Xhr()

;(async() => {
  const response = await termPolicyCreateXhr(1, 2, 3, {
    some: 'data',
  })
})()

@heisian
Copy link
Copy Markdown
Author

heisian commented Nov 20, 2019

simplified, after speaking IRL w/ @roblevintennis:

import xhr from 'xhr'

;(async() => {

  const path = new xhr.path
    .user(userId)
    .identity(identityId)
    .termPolicy(termPolicyId)

  // Xhr calls fetch internally
  const { err, response } = await xhr({
    baseURL: 'somethingelse.com',
    method: xhr.POST,
    path,
    { some: 'data' },
  })

  if (err) {
    // handle it
  }

})()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment