Migrating from jquery.ajax to request

This commit is contained in:
James Barnsley
2019-09-10 07:40:26 +12:00
parent c08cc71c47
commit 26b38cd0f9
6 changed files with 135 additions and 1908 deletions

View File

@ -19,7 +19,19 @@ const sendRequest = (dispatch, getState, endpoint, params) => new Promise((resol
const loader_key = helpers.generateGuid();
dispatch(uiActions.startLoading(loader_key, `discogs_${endpoint}`));
const checkRateLimit = (request) => {
const config = {
method: 'GET',
timeout: 30000,
mode: 'cors',
headers: {
'User-Agent': 'Iris/1.0',
'Authorization': `Discogs key=${key}, secret=${secret}`
},
};
function status(response) {
dispatch(uiActions.stopLoading(loader_key));
const rate = {
limit: request.getResponseHeader('X-Discogs-Ratelimit'),
remaining: request.getResponseHeader('X-Discogs-Ratelimit-Remaining'),
@ -33,38 +45,23 @@ const sendRequest = (dispatch, getState, endpoint, params) => new Promise((resol
description: `Discogs rate limit exceeded, try again in a few minutes.`
}));
}
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
const config = {
method: 'GET',
cache: true,
timeout: 30000,
url: url,
crossDomain: true,
headers: {
'User-Agent': 'Iris/1.0',
'Authorization': `Discogs key=${key}, secret=${secret}`
},
};
$.ajax(config).then(
(data, textStatus, request) => {
dispatch(uiActions.stopLoading(loader_key));
checkRateLimit(request);
fetch(url, config)
.then(status)
.then(response => response.json())
.then(data => {
resolve(data);
},
(xhr, status, error) => {
dispatch(uiActions.stopLoading(loader_key));
checkRateLimit(xhr);
reject({
config,
error,
status,
xhr,
});
},
);
})
.catch(error => {
reject(error);
});
});
export function getArtistImages(uri, artist) {

View File

@ -1,5 +1,4 @@
import axios from 'axios';
const coreActions = require('../core/actions');
const uiActions = require('../ui/actions');
const helpers = require('../../helpers');
@ -35,7 +34,6 @@ const sendRequest = (dispatch, getState, params, signed = false) => new Promise(
const config = {
method: http_method,
timeout: 30000,
cache: "force-cache",
};
const loader_key = helpers.generateGuid();

View File

@ -15,7 +15,7 @@ const helpers = require('../../helpers');
* @param data mixed = request payload
* @return Promise
* */
const request = (dispatch, getState, endpoint, method = 'GET', data = false) => {
const request = (dispatch, getState, endpoint, method = 'GET', data = false) => {
// Add reference to loader queue
// We do this straight away so that even if we're refreshing the token, it still registers as
// loading said endpoint
@ -25,7 +25,7 @@ const request = (dispatch, getState, endpoint, method = 'GET', data = false) =>
return new Promise((resolve, reject) => {
getToken(dispatch, getState)
.then(
(response) => {
(response) => {
// prepend the API baseurl, unless the endpoint already has it (ie pagination requests)
let url = `https://api.spotify.com/v1/${endpoint}`;
if (endpoint.startsWith('https://api.spotify.com/')) {
@ -35,7 +35,6 @@ const request = (dispatch, getState, endpoint, method = 'GET', data = false) =>
// create our ajax request config
const config = {
method,
url,
cached: true,
timeout: 30000,
headers: {
@ -53,33 +52,37 @@ const request = (dispatch, getState, endpoint, method = 'GET', data = false) =>
}
}
$.ajax(config).then(
(response) => {
dispatch(uiActions.stopLoading(loader_key));
resolve(response);
},
(xhr, status, error) => {
dispatch(uiActions.stopLoading(loader_key));
function status(response) {
dispatch(uiActions.stopLoading(loader_key));
// TODO: Rate limiting
if (xhr.status == 429) {
alert('You hit the Spotify API rate limiter');
}
// TODO: Rate limiting
if (response.status == 429) {
alert('You hit the Spotify API rate limiter');
}
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
fetch(url, config)
.then(status)
.then(response => response.json())
.then(data => {
// TODO: Instead of allowing request to fail before renewing the token, once refreshed
// we should retry the original request(s)
if (xhr.responseJSON && xhr.responseJSON.error && xhr.responseJSON.error.message == 'The access token expired') {
if (data.error && data.error.message == 'The access token expired') {
dispatch(refreshToken(dispatch, getState));
}
reject({
config,
xhr,
status,
error,
});
},
);
resolve(data);
})
.catch(error => {
reject(error);
});
},
(error) => {
dispatch(coreActions.handleException(
@ -99,7 +102,7 @@ const request = (dispatch, getState, endpoint, method = 'GET', data = false) =>
* @return Promise
* */
function getToken(dispatch, getState) {
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
// token is okay for now, so just resolve with the current token
if (getState().spotify.token_expiry && new Date().getTime() < getState().spotify.token_expiry) {
resolve(getState().spotify.access_token);
@ -111,7 +114,7 @@ function getToken(dispatch, getState) {
// need to wait until it's done, and then return that
// We've already got a refresh in progress
if (getState().ui.load_queue.spotify_refresh_token !== undefined) {
if (getState().ui.load_queue.spotify_refresh_token !== undefined) {
console.log("Already refreshing token, we'll wait 1000ms and try again");
// Re-check the queue periodically to see if it's finished yet
@ -137,13 +140,13 @@ function getToken(dispatch, getState) {
}
function refreshToken(dispatch, getState) {
return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
// add reference to loader queue
const loader_key = helpers.generateGuid();
dispatch(uiActions.startLoading(loader_key, 'spotify_refresh_token'));
// Fully-authorized, so we can use the local Spotify credentials
if (getState().spotify.authorization) {
if (getState().spotify.authorization) {
var config = {
method: 'GET',
url: `${getState().spotify.authorization_url}?action=refresh&refresh_token=${getState().spotify.refresh_token}`,
@ -178,7 +181,7 @@ function refreshToken(dispatch, getState) {
// Server-side authorized (with limited scope) so we need to refresh
// using the Mopidy-Spotify credentials
} else {
} else {
var config = {
method: 'GET',
url: `//${getState().mopidy.host}:${getState().mopidy.port}/iris/http/refresh_spotify_token`,
@ -197,7 +200,7 @@ function refreshToken(dispatch, getState) {
xhr,
status,
error: response.error,
});
});
} else {
const token = response.result.spotify_token;
token.token_expiry = new Date().getTime() + (token.expires_in * 1000);
@ -208,7 +211,7 @@ function refreshToken(dispatch, getState) {
data: token,
});
resolve(token);
}
}
},
(xhr, status, error) => {
dispatch(uiActions.stopLoading(loader_key));
@ -221,7 +224,7 @@ function refreshToken(dispatch, getState) {
});
},
);
}
}
});
}
@ -342,7 +345,7 @@ export function getLibraryTracks() {
}
export function getFeaturedPlaylists() {
return (dispatch, getState) => {
return (dispatch, getState) => {
dispatch({ type: 'SPOTIFY_FEATURED_PLAYLISTS_LOADED', data: false });
const date = new Date();
@ -542,7 +545,7 @@ export function clearSearchResults() {
}
export function getSearchResults(type, query, limit = 50, offset = 0) {
return (dispatch, getState) => {
return (dispatch, getState) => {
dispatch(uiActions.startProcess('SPOTIFY_GET_SEARCH_RESULTS_PROCESSOR', 'Searching Spotify'));
type = type.replace(/s+$/, '');
@ -634,7 +637,7 @@ export function getSearchResults(type, query, limit = 50, offset = 0) {
}
export function getAutocompleteResults(field_id, query, types = ['album', 'artist', 'playlist', 'track']) {
return (dispatch, getState) => {
return (dispatch, getState) => {
dispatch({ type: 'SPOTIFY_AUTOCOMPLETE_LOADING', field_id });
const genre_included = types.includes('genre');
@ -712,12 +715,12 @@ export function clearAutocompleteResults(field_id = null) {
}
export function following(uri, method = 'GET') {
return (dispatch, getState) => {
return (dispatch, getState) => {
if (method == 'PUT') var is_following = true;
if (method == 'DELETE') var is_following = false;
const asset_name = helpers.uriType(uri);
let endpoint; let
let endpoint; let
data;
switch (asset_name) {
case 'track':
@ -787,7 +790,7 @@ export function following(uri, method = 'GET') {
* @param radio object
* */
export function resolveRadioSeeds(radio) {
return (dispatch, getState) => {
return (dispatch, getState) => {
if (radio.seed_artists.length > 0) {
let artist_ids = '';
for (var i = 0; i < radio.seed_artists.length; i++) {
@ -855,7 +858,7 @@ export function resolveRadioSeeds(radio) {
* @param uri string
* */
export function getFavorites(limit = 50, term = 'long_term') {
return (dispatch, getState) => {
return (dispatch, getState) => {
dispatch({ type: 'SPOTIFY_FAVORITES_LOADED', artists: [], tracks: [] });
$.when(
@ -888,7 +891,7 @@ export function getFavorites(limit = 50, term = 'long_term') {
* @param uris = array of artist or track URIs or a genre string
* */
export function getRecommendations(uris = [], limit = 20, tunabilities = null) {
return (dispatch, getState) => {
return (dispatch, getState) => {
dispatch({ type: 'CLEAR_SPOTIFY_RECOMMENDATIONS' });
// build our starting point
@ -899,7 +902,7 @@ export function getRecommendations(uris = [], limit = 20, tunabilities = null) {
for (let i = 0; i < uris.length; i++) {
const uri = uris[i];
switch (helpers.uriType(uri)) {
switch (helpers.uriType(uri)) {
case 'artist':
artists_ids.push(helpers.getFromUri('artistid', uri));
break;
@ -1037,7 +1040,7 @@ export function getGenres() {
* @param full boolean (whether we want a full artist object)
* */
export function getArtist(uri, full = false) {
return (dispatch, getState) => {
return (dispatch, getState) => {
// Start with an empty object
// As each requests completes, they'll add to this object
const artist = {};
@ -1059,7 +1062,7 @@ export function getArtist(uri, full = false) {
];
// Do we want a full artist, with all supporting material?
if (full) {
if (full) {
requests.push(
request(dispatch, getState, `artists/${helpers.getFromUri('artistid', uri)}/top-tracks?country=${getState().spotify.country}`)
.then(
@ -1093,7 +1096,7 @@ export function getArtist(uri, full = false) {
}
// Run our requests
$.when.apply($, requests).then(() => {
$.when.apply($, requests).then(() => {
if (artist.musicbrainz_id) {
dispatch(lastfmActions.getArtist(artist.uri, false, artist.musicbrainz_id));
} else {
@ -1126,7 +1129,7 @@ export function getArtist(uri, full = false) {
}
export function getArtists(uris) {
return (dispatch, getState) => {
return (dispatch, getState) => {
// now get all the artists for this album (full objects)
let ids = '';
for (let i = 0; i < uris.length; i++) {
@ -1213,13 +1216,13 @@ export function getUser(uri) {
}
export function getUserPlaylists(uri) {
return (dispatch, getState) => {
return (dispatch, getState) => {
// get the first page of playlists
request(dispatch, getState, `users/${helpers.getFromUri('userid', uri)}/playlists?limit=40`)
.then(
(response) => {
const playlists = [];
for (const raw_playlist of response.items) {
for (const raw_playlist of response.items) {
let can_edit = false;
if (getState().spotify.me && raw_playlist.owner.id == getState().spotify.me.id) {
can_edit = true;
@ -1259,11 +1262,11 @@ export function getUserPlaylists(uri) {
* @oaram uri string
* */
export function getAlbum(uri) {
return (dispatch, getState) => {
return (dispatch, getState) => {
// get the album
request(dispatch, getState, `albums/${helpers.getFromUri('albumid', uri)}`)
.then(
(response) => {
(response) => {
// dispatch our loaded artists (simple objects)
dispatch(coreActions.artistsLoaded(response.artists));
@ -1308,7 +1311,7 @@ export function getAlbum(uri) {
error,
));
},
);
);
},
(error) => {
dispatch(coreActions.handleException(
@ -1351,7 +1354,7 @@ export function toggleAlbumInLibrary(uri, method) {
* */
export function createPlaylist(name, description, is_public, is_collaborative) {
return (dispatch, getState) => {
return (dispatch, getState) => {
const data = {
name,
description,
@ -1371,7 +1374,7 @@ export function createPlaylist(name, description, is_public, is_collaborative) {
can_edit: true,
tracks: [],
tracks_more: null,
tracks_total: 0,
tracks_total: 0,
},
});
@ -1393,7 +1396,7 @@ export function createPlaylist(name, description, is_public, is_collaborative) {
}
export function savePlaylist(uri, name, description, is_public, is_collaborative, image) {
return (dispatch, getState) => {
return (dispatch, getState) => {
const data = {
name,
description,
@ -1403,7 +1406,7 @@ export function savePlaylist(uri, name, description, is_public, is_collaborative
// Update the playlist fields
request(
dispatch, getState, `users/${getState().spotify.me.id}/playlists/${helpers.getFromUri('playlistid', uri)}`, 'PUT', data,
dispatch, getState, `users/${getState().spotify.me.id}/playlists/${helpers.getFromUri('playlistid', uri)}`, 'PUT', data,
)
.then(
(response) => {
@ -1459,11 +1462,11 @@ export function savePlaylist(uri, name, description, is_public, is_collaborative
}
export function getPlaylist(uri) {
return (dispatch, getState) => {
return (dispatch, getState) => {
// get the main playlist object
request(dispatch, getState, `playlists/${helpers.getFromUri('playlistid', uri)}?market=${getState().spotify.country}`)
.then(
(response) => {
(response) => {
// convert links in description
let description = null;
if (response.description) {
@ -1523,7 +1526,7 @@ export function getLibraryTracksAndPlayProcessor(data) {
return (dispatch, getState) => {
request(dispatch, getState, data.next)
.then(
(response) => {
(response) => {
// Check to see if we've been cancelled
if (getState().ui.processes.SPOTIFY_GET_LIBRARY_TRACKS_AND_PLAY_PROCESSOR !== undefined) {
const processor = getState().ui.processes.SPOTIFY_GET_LIBRARY_TRACKS_AND_PLAY_PROCESSOR;
@ -1607,7 +1610,7 @@ export function getAllPlaylistTracksProcessor(data) {
return (dispatch, getState) => {
request(dispatch, getState, data.next)
.then(
(response) => {
(response) => {
// Check to see if we've been cancelled
if (getState().ui.processes.SPOTIFY_GET_ALL_PLAYLIST_TRACKS_PROCESSOR !== undefined) {
const processor = getState().ui.processes.SPOTIFY_GET_ALL_PLAYLIST_TRACKS_PROCESSOR;
@ -1654,7 +1657,7 @@ export function getAllPlaylistTracksProcessor(data) {
uris,
},
));
} else {
} else {
if (data.shuffle) {
uris = helpers.shuffle(uris);
}
@ -1751,8 +1754,8 @@ export function deleteTracksFromPlaylist(uri, snapshot_id, tracks_indexes) {
export function reorderPlaylistTracks(uri, range_start, range_length, insert_before, snapshot_id) {
return (dispatch, getState) => {
request(dispatch, getState, `playlists/${helpers.getFromUri('playlistid', uri)}/tracks`, 'PUT', {
uri, range_start, range_length, insert_before, snapshot_id,
request(dispatch, getState, `playlists/${helpers.getFromUri('playlistid', uri)}/tracks`, 'PUT', {
uri, range_start, range_length, insert_before, snapshot_id,
})
.then(
(response) => {
@ -1996,4 +1999,4 @@ export function getLibraryAlbumsProcessor(data) {
},
);
};
}
}