-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathPromiseMiddleware.js
More file actions
59 lines (54 loc) · 1.69 KB
/
PromiseMiddleware.js
File metadata and controls
59 lines (54 loc) · 1.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
* PromiseMiddleware
*
* Lets you dispatch special actions with a { promise } field.
*
* This middleware will turn them into a single action at the beginning,
* and a single success (or failure) action when the `promise` resolves.
* It also generates a unique ID for the special meta sequence object
* that it attaches to the action, see issue#7 in flux-standard-action,
* https://github.com/acdlite/flux-standard-action/issues/7
*
* For convenience, `dispatch` will return the promise so the caller can wait.
*
*/
export const START = 'START';
export const DONE = 'DONE';
function generateRandomId() {
return Math.random()
.toString(36)
.slice(-5);
}
function sequence(id, type) {
return {
sequence: { id, type },
};
}
export default function PromiseMiddleware() {
return next => action => {
const { promise, ...rest } = action;
const id = generateRandomId();
if (!promise) {
return next(action);
}
next({ ...rest, ...sequence(id, START) });
return promise.then(
payload => next({ ...rest, payload, ...sequence(id, DONE) }),
reason => {
let error = reason;
// By FSA definition, payload SHOULD be an error object
// Promises in turn don't require reason to be an Error
if (!(error instanceof Error)) {
let message = reason;
if (typeof message !== 'string') {
message = 'Promise rejected with data. See error.data field.';
}
error = new Error(message);
error.data = reason;
}
next({ ...rest, payload: error, error: true, ...sequence(id) });
return Promise.reject(reason); // Don't break the promise chain
}
);
};
}