Files
cellxgene/client/src/util/actionHelpers.js
T
Bruce Martin 00a68276a2 diffexp performance & UX improvements (#431)
* new diffexp REST API spec

* new diffexp REST API; faster diffexp and dataframe slicing

* first draft of fast diffexp

* convert variance calculation to two-pass method

* lint

* update front-end use of API

* fix typo in spec

* disable content compression

* catch index filter format errors

* clean up of dead code

* resolve PR review comments
2018-11-14 12:51:24 -08:00

99 lines
2.5 KiB
JavaScript

import _ from "lodash";
/* XXX: cough, cough, ... */
import { postNetworkErrorToast } from "../components/framework/toasters";
/*
dispatch an action error to the user. Currently we use
async toasts.
*/
export const dispatchNetworkErrorMessageToUser = message =>
postNetworkErrorToast(message);
/*
Catch unexpected errors and make sure we don't lose them!
*/
export function catchErrorsWrap(fn, dispatchToUser = false) {
return (dispatch, getState) => {
fn(dispatch, getState).catch(error => {
console.error(error);
if (dispatchToUser) {
dispatchNetworkErrorMessageToUser(error.message);
}
dispatch({ type: "UNEXPECTED ERROR", error });
});
};
}
/*
Wrapper to perform an async fetch and JSON decode response.
*/
export const doJsonRequest = async url => {
const res = await fetch(url, {
method: "get",
headers: new Headers({
"Content-Type": "application/json"
})
});
if (res.ok && res.headers.get("Content-Type") === "application/json") {
return res.json();
}
// else an error
const msg = `Unexpected HTTP response ${res.status}, ${res.statusText}`;
dispatchNetworkErrorMessageToUser(msg);
throw new Error(msg);
};
/*
This function "packs" filter index lists into the more efficient
"range" form specified in the REST 0.2 spec.
Specifically, it turns an array of indices [0, 1, 2, 10, 11, 14, ...]
into a form that encodes runs of consecutive numbers as [min, max].
Array may not be sorted, but will only contain uniq values.
Parameters:
indices - input array of numbers (index)
minRangeLength - hint, min range length before it is encoded into range format.
sorted - boolean hint indicating array is presorted, ascending order
So [1, 2, 3, 4, 10, 11, 14] -> [ [1, 4], [10, 11], 14]
*/
export const rangeEncodeIndices = (
indices,
minRangeLength = 3,
sorted = false
) => {
if (indices.length === 0) {
return indices;
}
if (!sorted) {
indices = _.sortBy(indices);
}
const result = new Array(indices.length);
let resultTail = 0;
let i = 0;
while (i < indices.length) {
const begin = indices[i];
let current;
do {
current = indices[i];
i += 1;
} while (i < indices.length && indices[i] === current + 1);
if (current - begin + 1 >= minRangeLength) {
result[resultTail] = [begin, current];
resultTail += 1;
} else {
for (let j = begin; j <= current; j += 1, resultTail += 1) {
result[resultTail] = j;
}
}
}
result.length = resultTail;
return result;
};