mirror of
https://github.com/status-im/MyCrypto.git
synced 2025-02-18 14:07:31 +00:00
Create a basic saga pattern to handle potential network errors. (#144)
* First pass at handling API failure. * Bity saga logic upgrade. * Reusable response.ok logic. Small optimization to array join. * Flow fixes. * Streamlined some error handling, moved types.
This commit is contained in:
parent
efee709d0f
commit
2616129409
@ -11,3 +11,14 @@ export function checkHttpStatus(response) {
|
|||||||
export function parseJSON(response) {
|
export function parseJSON(response) {
|
||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function handleJSONResponse(response, errorMessage) {
|
||||||
|
if (response.ok) {
|
||||||
|
const json = await response.json();
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
if (errorMessage) {
|
||||||
|
throw new Error(errorMessage);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -1,19 +1,28 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { put, call } from 'redux-saga/effects';
|
import { put, call } from 'redux-saga/effects';
|
||||||
import type { Effect } from 'redux-saga/effects';
|
|
||||||
|
import { handleJSONResponse } from 'api/utils';
|
||||||
|
|
||||||
import { setRates } from 'actions/rates';
|
import { setRates } from 'actions/rates';
|
||||||
|
import { showNotification } from 'actions/notifications';
|
||||||
|
|
||||||
|
import type { Yield, Return, Next } from 'sagas/types';
|
||||||
|
|
||||||
const symbols = ['USD', 'EUR', 'GBP', 'BTC', 'CHF', 'REP'];
|
const symbols = ['USD', 'EUR', 'GBP', 'BTC', 'CHF', 'REP'];
|
||||||
|
const symbolsURL = symbols.join(',');
|
||||||
|
|
||||||
function fetchRates(symbols) {
|
const fetchRates = () =>
|
||||||
return fetch(
|
fetch(
|
||||||
`https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=${symbols.join(
|
`https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=${symbolsURL}`
|
||||||
','
|
).then(response =>
|
||||||
)}`
|
handleJSONResponse(response, 'Could not fetch rate data.')
|
||||||
).then(r => r.json());
|
);
|
||||||
}
|
|
||||||
|
|
||||||
export default function* ratesSaga(): Generator<Effect, void, any> {
|
export default function* ratesSaga(): Generator<Yield, Return, Next> {
|
||||||
const rates = yield call(fetchRates, symbols);
|
try {
|
||||||
yield put(setRates(rates));
|
const rates = yield call(fetchRates);
|
||||||
|
yield put(setRates(rates));
|
||||||
|
} catch (error) {
|
||||||
|
yield put(showNotification('danger', error));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,37 +1,34 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { delay } from 'redux-saga';
|
import { delay } from 'redux-saga';
|
||||||
|
import { call, cancel, fork, put, take, takeLatest } from 'redux-saga/effects';
|
||||||
|
|
||||||
import { getAllRates } from 'api/bity';
|
import { getAllRates } from 'api/bity';
|
||||||
import { call, put, fork, take, cancel, cancelled } from 'redux-saga/effects';
|
|
||||||
import type { Effect } from 'redux-saga/effects';
|
|
||||||
import { loadBityRatesSucceededSwap } from 'actions/swap';
|
import { loadBityRatesSucceededSwap } from 'actions/swap';
|
||||||
|
import { showNotification } from 'actions/notifications';
|
||||||
|
|
||||||
export function* loadBityRates(_action?: any): Generator<Effect, void, any> {
|
import type { Yield, Return, Next } from 'sagas/types';
|
||||||
try {
|
|
||||||
while (true) {
|
export function* loadBityRates(_action?: any): Generator<Yield, Return, Next> {
|
||||||
// TODO - BITY_RATE_REQUESTED
|
while (true) {
|
||||||
// network request
|
try {
|
||||||
const data = yield call(getAllRates);
|
const data = yield call(getAllRates);
|
||||||
// action
|
|
||||||
yield put(loadBityRatesSucceededSwap(data));
|
yield put(loadBityRatesSucceededSwap(data));
|
||||||
// wait 5 seconds before refreshing rates
|
} catch (error) {
|
||||||
yield call(delay, 5000);
|
yield put(yield showNotification('danger', error));
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (yield cancelled()) {
|
|
||||||
// TODO - implement request cancel if needed
|
|
||||||
// yield put(actions.requestFailure('Request cancelled!'))
|
|
||||||
}
|
}
|
||||||
|
yield call(delay, 5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* getBityRatesSaga(): Generator<Effect, void, any> {
|
// Fork our recurring API call, watch for the need to cancel.
|
||||||
while (yield take('SWAP_LOAD_BITY_RATES_REQUESTED')) {
|
function* handleBityRates(): Generator<Yield, Return, Next> {
|
||||||
// starts the task in the background
|
const loadBityRatesTask = yield fork(loadBityRates);
|
||||||
const loadBityRatesTask = yield fork(loadBityRates);
|
yield take('SWAP_STOP_LOAD_BITY_RATES');
|
||||||
// wait for the user to get to point where refresh is no longer needed
|
yield cancel(loadBityRatesTask);
|
||||||
yield take('SWAP_STOP_LOAD_BITY_RATES');
|
}
|
||||||
// cancel the background task
|
|
||||||
// this will cause the forked loadBityRates task to jump into its finally block
|
// Watch for latest SWAP_LOAD_BITY_RATES_REQUESTED action.
|
||||||
yield cancel(loadBityRatesTask);
|
export function* getBityRatesSaga(): Generator<Yield, Return, Next> {
|
||||||
}
|
yield takeLatest('SWAP_LOAD_BITY_RATES_REQUESTED', handleBityRates);
|
||||||
}
|
}
|
||||||
|
5
common/sagas/types.js
Normal file
5
common/sagas/types.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import type { Effect } from 'redux-saga/effects';
|
||||||
|
|
||||||
|
export type Yield = Effect | {};
|
||||||
|
export type Return = void;
|
||||||
|
export type Next = any;
|
Loading…
x
Reference in New Issue
Block a user