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

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -100,7 +100,7 @@
// Release details
// These are automatically injected to built HTML
var build = "1568011497";
var build = "1568057591";
var version = "3.40.0";
// Construct the script tag

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) {
},
);
};
}
}