Skip to content
This repository was archived by the owner on Jun 4, 2024. It is now read-only.

Commit 96d5c46

Browse files
committed
reject old responses of the same output component
fixes plotly/dash#133
1 parent c3b5ece commit 96d5c46

File tree

4 files changed

+63
-19
lines changed

4 files changed

+63
-19
lines changed

src/actions/index.js

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
/* global fetch:true, Promise:true, document:true */
22
import {
3+
adjust,
4+
any,
35
concat,
46
contains,
7+
findIndex,
8+
findLastIndex,
59
has,
610
intersection,
711
isEmpty,
812
keys,
913
lensPath,
14+
lensProp,
1015
pluck,
11-
reject,
16+
propEq,
17+
set,
1218
slice,
1319
sort,
1420
type,
15-
union,
1621
view
1722
} from 'ramda';
1823
import {createAction} from 'redux-actions';
1924
import {crawlLayout, hasId} from '../reducers/utils';
2025
import {APP_STATES} from '../reducers/constants';
2126
import {ACTIONS} from './constants';
2227
import cookie from 'cookie';
23-
import {urlBase} from '../utils';
28+
import {uid, urlBase} from '../utils';
2429

2530
export const updateProps = createAction(ACTIONS('ON_PROP_CHANGE'));
2631
export const setRequestQueue = createAction(ACTIONS('SET_REQUEST_QUEUE'));
@@ -253,8 +258,9 @@ export function notifyObservers(payload) {
253258
* the change for Child. if this update has already been queued up,
254259
* then skip the update for the other component
255260
*/
256-
const controllersInExistingQueue = intersection(
257-
requestQueue, controllers
261+
const controllerIsInExistingQueue = any(r =>
262+
contains(r.controllerId, controllers) && r.status === 'loading',
263+
requestQueue
258264
);
259265

260266
/*
@@ -267,7 +273,7 @@ export function notifyObservers(payload) {
267273
if (
268274
(controllersInFutureQueue.length === 0) &&
269275
(has(outputComponentId, getState().paths)) &&
270-
(controllersInExistingQueue.length === 0)
276+
!controllerIsInExistingQueue
271277
) {
272278
queuedObservers.push(outputIdAndProp)
273279
}
@@ -278,7 +284,15 @@ export function notifyObservers(payload) {
278284
* updated in a queue. not all of these requests will be fired in this
279285
* action
280286
*/
281-
dispatch(setRequestQueue(union(queuedObservers, requestQueue)));
287+
const newRequestQueue = queuedObservers.map(
288+
i => ({controllerId: i, status: 'loading', uid: uid()})
289+
)
290+
dispatch(setRequestQueue(
291+
concat(
292+
requestQueue,
293+
newRequestQueue
294+
)
295+
));
282296

283297
const promises = [];
284298
for (let i = 0; i < queuedObservers.length; i++) {
@@ -356,13 +370,33 @@ export function notifyObservers(payload) {
356370
payload: {status: res.status}
357371
});
358372

359-
// clear this item from the request queue
360-
dispatch(setRequestQueue(
361-
reject(
362-
id => id === outputIdAndProp,
363-
getState().requestQueue
364-
)
365-
));
373+
// update the status of this request
374+
const postRequestQueue = getState().requestQueue;
375+
const requestUid = newRequestQueue[i].uid;
376+
const thisRequestIndex = findIndex(
377+
propEq('uid', requestUid),
378+
postRequestQueue
379+
);
380+
const updatedQueue = adjust(
381+
set(lensProp('status'), res.status),
382+
thisRequestIndex,
383+
postRequestQueue
384+
);
385+
dispatch(setRequestQueue(updatedQueue));
386+
387+
/*
388+
* Check to see if another request has already come back
389+
* _after_ this one.
390+
* If so, ignore this request.
391+
*/
392+
const latestRequestIndex = findLastIndex(
393+
propEq('controllerId', newRequestQueue[i].controllerId),
394+
updatedQueue
395+
);
396+
if (latestRequestIndex > thisRequestIndex &&
397+
updatedQueue[latestRequestIndex].status === 200) {
398+
return;
399+
}
366400

367401
return res.json().then(function handleJson(data) {
368402

src/components/core/DocumentTitle.react.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* global document:true */
22

33
import {connect} from 'react-redux'
4-
import {isEmpty} from 'ramda'
4+
import {any} from 'ramda'
55
import {Component, PropTypes} from 'react'
66

77
class DocumentTitle extends Component {
@@ -13,7 +13,7 @@ class DocumentTitle extends Component {
1313
}
1414

1515
componentWillReceiveProps(props) {
16-
if (!isEmpty(props.requestQueue)) {
16+
if (any(r => r.status === 'loading', props.requestQueue)) {
1717
document.title = 'Updating...';
1818
} else {
1919
document.title = this.state.initialTitle;

src/components/core/Loading.react.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import {connect} from 'react-redux'
2-
import {isEmpty} from 'ramda'
2+
import {any} from 'ramda'
33
import React, {PropTypes} from 'react'
44

55
function Loading(props) {
6-
if (!isEmpty(props.requestQueue)) {
6+
if (any(r => r.status === 'loading', props.requestQueue)) {
77
return (
88
<div className="_dash-loading-callback"/>
9-
)
9+
);
1010
} else {
1111
return null;
1212
}

src/utils.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,13 @@ export function urlBase(config) {
2525
requests_pathname_prefix from config`, config);
2626
}
2727
}
28+
29+
export function uid() {
30+
function s4() {
31+
return Math.floor((1 + Math.random()) * 0x10000)
32+
.toString(16)
33+
.substring(1);
34+
}
35+
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
36+
s4() + '-' + s4() + s4() + s4();
37+
}

0 commit comments

Comments
 (0)