Last active
May 14, 2018 14:11
-
-
Save zeraphie/547aa3b7ebbe6221df5e4e4fb4ca6e7f to your computer and use it in GitHub Desktop.
A fetch wrapper that takes the same parameters and formats the fetch request for you
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default class SuperFetch { | |
constructor(url, data, params = {}){ | |
this.url = url; | |
this.data = data; | |
this.params = params; | |
} | |
/** | |
* Send a get request using the fetch api | |
* | |
* @returns {Promise<Response>} | |
*/ | |
async get(){ | |
let url = this.url; | |
if(this.constructor.isObject(this.data)){ | |
if(this.data instanceof FormData){ | |
let parsed = {}; | |
[...this.data.keys()].map(key => parsed[key] = this.data.get(key)); | |
url += '?' + this.constructor.queryParameters(parsed); | |
} else { | |
url += '?' + this.constructor.queryParameters(this.data); | |
} | |
} | |
return await fetch(url, this.mergeParams({ | |
method: 'GET' | |
})); | |
} | |
/** | |
* Send a post request using the fetch api | |
* | |
* @returns {Promise<Response>} | |
*/ | |
async post(){ | |
if(this.constructor.isObject(this.data)){ | |
if(this.data instanceof FormData){ | |
this.params.body = this.data; | |
} else { | |
this.params.body = JSON.stringify(this.data); | |
} | |
} | |
return await fetch(this.url, this.mergeParams({ | |
method: 'POST' | |
})); | |
} | |
/** | |
* Send a put request using the fetch api | |
* | |
* @returns {Promise<Response>} | |
*/ | |
async put(){ | |
if(this.constructor.isObject(this.data)){ | |
if(this.data instanceof FormData){ | |
this.data.append('_method', 'PUT'); | |
this.params.body = this.data; | |
} else { | |
this.data['_method'] = 'PUT'; | |
this.params.body = JSON.stringify(this.data); | |
} | |
} | |
return await fetch(this.url, this.mergeParams({ | |
method: 'POST' | |
})); | |
} | |
/** | |
* Send a patch request using the fetch api | |
* | |
* @returns {Promise<Response>} | |
*/ | |
async patch(){ | |
if(this.constructor.isObject(this.data)){ | |
if(this.data instanceof FormData){ | |
this.data.append('_method', 'PATCH'); | |
this.params.body = this.data; | |
} else { | |
this.data['_method'] = 'PATCH'; | |
this.params.body = JSON.stringify(this.data); | |
} | |
} | |
return await fetch(this.url, this.mergeParams({ | |
method: 'POST' | |
})); | |
} | |
/** | |
* Send a delete request using the fetch api | |
* | |
* @returns {Promise<Response>} | |
*/ | |
async delete(){ | |
return await fetch(this.url, this.mergeParams({ | |
method: 'DELETE' | |
})); | |
} | |
/** | |
* Send a get request using the fetch api and convert the response to text | |
* | |
* @param method | |
* @returns {Promise<*>} | |
*/ | |
async text(method = 'GET'){ | |
if(method === 'GET'){ | |
let got = await this.get(); | |
return await got.text(); | |
} | |
if(method === 'POST'){ | |
let posted = await this.post(); | |
return await posted.text(); | |
} | |
return Promise.reject('Bad Method: ' + method); | |
} | |
/** | |
* Send a get request using the fetch api and convert the response to json | |
* | |
* @param method | |
* @returns {Promise<*>} | |
*/ | |
async json(method = 'GET'){ | |
if(method === 'GET'){ | |
let got = await this.get(); | |
return await got.json(); | |
} | |
if(method === 'POST'){ | |
let posted = await this.post(); | |
return await posted.json(); | |
} | |
return Promise.reject('Bad Method: ' + method); | |
} | |
/** | |
* Override the parameters | |
* | |
* @param overrides | |
* @returns {{}} | |
*/ | |
mergeParams(overrides){ | |
// Only allow same origin | |
const unchangeable = { | |
mode: 'same-origin', | |
credentials: 'same-origin' | |
}; | |
// Add the token if it's present for post requests | |
const token = this.constructor.getToken(); | |
if(token){ | |
unchangeable.headers = new Headers({ | |
'X-CSRF-TOKEN': this.constructor.getToken(), | |
}); | |
} | |
// Return a combined params object | |
return { | |
...this.params, | |
...overrides, | |
...unchangeable, | |
}; | |
} | |
/** | |
* Get the csrf token on the page or return false if not found | |
* | |
* @returns {*} | |
*/ | |
static getToken(){ | |
// Typical csrf token elements (present in laravel) | |
const metaTokenElement = document.querySelector('meta[name="csrf-token"]'); | |
const inputTokenElement = document.querySelector('input[name="_token"]'); | |
if(metaTokenElement){ | |
return metaTokenElement.getAttribute('content'); | |
} | |
if(inputTokenElement){ | |
return inputTokenElement.value; | |
} | |
return false; | |
} | |
/** | |
* Convert an object into query string | |
* | |
* @param obj | |
* @returns {string} | |
*/ | |
static queryParameters(obj){ | |
return Object.keys(obj).map( | |
p => encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]) | |
).join('&'); | |
} | |
/** | |
* Test if the thing is an object | |
* | |
* @param thing | |
* @returns {boolean} | |
*/ | |
static isObject(thing){ | |
if(thing === null){ | |
return false; | |
} | |
return ((typeof thing === 'function') || (typeof thing === 'object')); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example Usage
Getting a response from a webpage using an object
Getting a response from a webpage using an object
Updating a field on a resource using an object
Updating a field on a resource using FormData