Socket
Socket
Sign inDemoInstall

redux-saga

Package Overview
Dependencies
Maintainers
1
Versions
74
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

redux-saga - npm Package Compare versions

Comparing version 0.5.0 to 0.6.0

lib/SagaCancellationException.js

658

dist/redux-saga.js

@@ -62,10 +62,10 @@ (function webpackUniversalModuleDefinition(root, factory) {

});
exports.monitorActions = exports.storeIO = exports.runSaga = exports.as = exports.cancel = exports.join = exports.fork = exports.cps = exports.apply = exports.call = exports.race = exports.put = exports.take = exports.is = exports.MANUAL_CANCEL = exports.PARALLEL_AUTO_CANCEL = exports.RACE_AUTO_CANCEL = exports.SagaCancellationException = undefined;
exports.monitorActions = exports.storeIO = exports.runSaga = exports.as = exports.cancel = exports.join = exports.fork = exports.cps = exports.apply = exports.call = exports.race = exports.put = exports.take = exports.is = exports.SagaCancellationException = exports.MANUAL_CANCEL = exports.PARALLEL_AUTO_CANCEL = exports.RACE_AUTO_CANCEL = exports.CANCEL = undefined;
var _proc = __webpack_require__(2);
var _proc = __webpack_require__(3);
Object.defineProperty(exports, 'SagaCancellationException', {
Object.defineProperty(exports, 'CANCEL', {
enumerable: true,
get: function get() {
return _proc.SagaCancellationException;
return _proc.CANCEL;
}

@@ -101,3 +101,3 @@ });

var _io = __webpack_require__(4);
var _io = __webpack_require__(6);

@@ -165,3 +165,3 @@ Object.defineProperty(exports, 'take', {

var _runSaga = __webpack_require__(7);
var _runSaga = __webpack_require__(8);

@@ -181,8 +181,12 @@ Object.defineProperty(exports, 'runSaga', {

var _middleware = __webpack_require__(6);
var _middleware = __webpack_require__(7);
var _middleware2 = _interopRequireDefault(_middleware);
var _monitorActions = __webpack_require__(5);
var _SagaCancellationException2 = __webpack_require__(4);
var _SagaCancellationException3 = _interopRequireDefault(_SagaCancellationException2);
var _monitorActions = __webpack_require__(2);
var monitorActions = _interopRequireWildcard(_monitorActions);

@@ -195,2 +199,4 @@

exports.default = _middleware2.default;
var SagaCancellationException = exports.SagaCancellationException = _SagaCancellationException3.default;
exports.monitorActions = monitorActions;

@@ -200,5 +206,5 @@

/* 1 */
/***/ function(module, exports) {
/***/ function(module, exports, __webpack_require__) {
'use strict';
/* WEBPACK VAR INJECTION */(function(process) {'use strict';

@@ -222,2 +228,4 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var isDev = exports.isDev = typeof process !== 'undefined' && process.env && ("development") === 'development';
function check(value, predicate, error) {

@@ -290,5 +298,44 @@ if (!predicate(value)) throw new Error(error);

}
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(9)))
/***/ },
/* 2 */
/***/ function(module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.effectTriggered = effectTriggered;
exports.effectResolved = effectResolved;
exports.effectRejected = effectRejected;
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var MONITOR_ACTION = exports.MONITOR_ACTION = 'MONITOR_ACTION';
var EFFECT_TRIGGERED = exports.EFFECT_TRIGGERED = 'EFFECT_TRIGGERED';
var EFFECT_RESOLVED = exports.EFFECT_RESOLVED = 'EFFECT_RESOLVED';
var EFFECT_REJECTED = exports.EFFECT_REJECTED = 'EFFECT_REJECTED';
function effectTriggered(effectId, parentEffectId, label, effect) {
var _ref;
return _ref = {}, _defineProperty(_ref, MONITOR_ACTION, true), _defineProperty(_ref, 'type', EFFECT_TRIGGERED), _defineProperty(_ref, 'effectId', effectId), _defineProperty(_ref, 'parentEffectId', parentEffectId), _defineProperty(_ref, 'label', label), _defineProperty(_ref, 'effect', effect), _ref;
}
function effectResolved(effectId, result) {
var _ref2;
return _ref2 = {}, _defineProperty(_ref2, MONITOR_ACTION, true), _defineProperty(_ref2, 'type', EFFECT_RESOLVED), _defineProperty(_ref2, 'effectId', effectId), _defineProperty(_ref2, 'result', result), _ref2;
}
function effectRejected(effectId, error) {
var _ref3;
return _ref3 = {}, _defineProperty(_ref3, MONITOR_ACTION, true), _defineProperty(_ref3, 'type', EFFECT_REJECTED), _defineProperty(_ref3, 'effectId', effectId), _defineProperty(_ref3, 'error', error), _ref3;
}
/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {

@@ -301,3 +348,3 @@

});
exports.SagaCancellationException = exports.CANCEL = exports.MANUAL_CANCEL = exports.RACE_AUTO_CANCEL = exports.PARALLEL_AUTO_CANCEL = exports.NOT_ITERATOR_ERROR = undefined;
exports.MANUAL_CANCEL = exports.RACE_AUTO_CANCEL = exports.PARALLEL_AUTO_CANCEL = exports.CANCEL = exports.NOT_ITERATOR_ERROR = undefined;
exports.default = proc;

@@ -307,8 +354,14 @@

var _io = __webpack_require__(4);
var _io = __webpack_require__(6);
var _monitorActions = __webpack_require__(5);
var _monitorActions = __webpack_require__(2);
var monitorActions = _interopRequireWildcard(_monitorActions);
var _SagaCancellationException = __webpack_require__(4);
var _SagaCancellationException2 = _interopRequireDefault(_SagaCancellationException);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

@@ -318,5 +371,4 @@

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var NOT_ITERATOR_ERROR = exports.NOT_ITERATOR_ERROR = 'proc first argument (Saga function result) must be an iterator';
var CANCEL = exports.CANCEL = Symbol('@@redux-saga/cancelPromise');
var PARALLEL_AUTO_CANCEL = exports.PARALLEL_AUTO_CANCEL = 'PARALLEL_AUTO_CANCEL';

@@ -328,12 +380,2 @@ var RACE_AUTO_CANCEL = exports.RACE_AUTO_CANCEL = 'RACE_AUTO_CANCEL';

var CANCEL = exports.CANCEL = Symbol('@@redux-saga/cancelPromise');
var SagaCancellationException = exports.SagaCancellationException = function SagaCancellationException(type, saga, origin) {
_classCallCheck(this, SagaCancellationException);
this.type = type;
this.saga = saga;
this.origin = origin;
};
function proc(iterator) {

@@ -350,28 +392,72 @@ var subscribe = arguments.length <= 1 || arguments[1] === undefined ? function () {

// tracks the current `take` effects
var deferredInputs = [];
var canThrow = _utils.is.throw(iterator);
// Promise to be resolved/rejected when this generator terminates (or throws)
var deferredEnd = (0, _utils.deferred)();
// subscribe to input events, this will resolve the current `take` effects
var unsubscribe = subscribe(function (input) {
deferredInputs.forEach(function (def) {
if (def.match(input)) def.resolve(input);
});
for (var i = 0; i < deferredInputs.length; i++) {
var def = deferredInputs[i];
if (def.match(input)) {
// cancel all deferredInputs; parallel takes are disallowed
// and in concurrent takes, first wins
deferredInputs = [];
def.resolve(input);
}
}
});
/**
cancel : (SagaCancellationException) -> ()
Tracks the current effect cancellation
Each time the generator progresses. calling runEffect will set a new value
on it. It allows propagating cancellation to child effects
**/
next.cancel = _utils.noop;
/**
Creates a new task descriptor for this generator
**/
var task = newTask(parentEffectId, name, iterator, deferredEnd.promise);
/**
this maybe called by a parent generator to trigger/propagate cancellation
W'll simply cancel the current effect, which will reject that effect
The rejection will throw the injected SagaCancellationException into the flow
of this generator
**/
task.done[CANCEL] = function (_ref) {
var type = _ref.type;
var origin = _ref.origin;
next.cancel(new _SagaCancellationException2.default(type, name, origin));
};
// tracks the running status
iterator._isRunning = true;
// kicks up the generator
next();
return newTask(parentEffectId, name, iterator, deferredEnd.promise);
// then return the task descriptor to the caller
return task;
function next(arg, isError) {
if (!iterator._isRunning) return;
/**
This is the generator driver
It's a recursive aysnc/continuation function which calls itself
until the generator terminates or throws
**/
function next(error, arg) {
// Preventive measure. If we endup here, then there is really something wrong
if (!iterator._isRunning) throw new Error('Trying to resume an already finished generator');
try {
if (isError && !canThrow) throw arg;
var result = isError ? iterator.throw(arg) : iterator.next(arg);
if (error && !canThrow) throw error;
// calling iterator.throw on a generator that doesnt defined a correponding try/Catch
var result = error ? iterator.throw(error) : iterator.next(arg);
if (!result.done) {
var currentEffect = runEffect(result.value, parentEffectId);
deferredEnd.promise[CANCEL] = currentEffect[CANCEL];
currentEffect.then(next, function (err) {
return next(err, true);
});
runEffect(result.value, parentEffectId, '', next);
} else {

@@ -382,3 +468,5 @@ end(result.value);

/*eslint-disable no-console*/
console.warn(name + ': uncaught', error);
if (_utils.isDev) {
console.warn(name + ': uncaught', error);
}
end(error, true);

@@ -402,2 +490,3 @@ }

var label = arguments.length <= 2 || arguments[2] === undefined ? '' : arguments[2];
var cb = arguments[3];

@@ -407,54 +496,111 @@ var effectId = nextEffectId();

var data = undefined;
var promise = _utils.is.array(effect) ? runParallelEffect(effect, effectId) : _utils.is.iterator(effect) ? proc(effect, subscribe, dispatch, monitor, effectId).done : (data = _io.as.take(effect)) ? runTakeEffect(data) : (data = _io.as.put(effect)) ? runPutEffect(data) : (data = _io.as.race(effect)) ? runRaceEffect(data, effectId) : (data = _io.as.call(effect)) ? runCallEffect(data, effectId) : (data = _io.as.cps(effect)) ? runCPSEffect(data) : (data = _io.as.fork(effect)) ? runForkEffect(data, effectId) : (data = _io.as.join(effect)) ? runJoinEffect(data) : (data = _io.as.cancel(effect)) ? runCancelEffect(data) : /* resolve anything else */Promise.resolve(effect);
/**
completion callback and cancel callback are mutually exclusive
We can't cancel an already completed effect
And We can't complete an already cancelled effectId
**/
var effectSettled = undefined;
var def = (0, _utils.deferred)();
var isRunning = true;
var completeWith = function completeWith(fn) {
return function (outcome) {
if (isRunning) {
isRunning = false;
fn(outcome);
}
};
};
promise.then(completeWith(def.resolve), completeWith(def.reject));
def.promise[CANCEL] = function (_ref) {
var type = _ref.type;
var origin = _ref.origin;
// Completion callback passed to the appropriate effect runner
function currCb(err, res) {
if (effectSettled) return;
if (isRunning) {
isRunning = false;
var error = new SagaCancellationException(type, name, origin);
cancelPromise(promise, error);
def.reject(error);
effectSettled = true;
cb.cancel = _utils.noop; // defensive measure
err ? monitor(monitorActions.effectRejected(effectId, err)) : monitor(monitorActions.effectResolved(effectId, res));
cb(err, res);
}
// tracks down the current cancel
currCb.cancel = _utils.noop;
// setup cancellation logic on the parent cb
cb.cancel = function (cancelError) {
// prevents cancelling an already completed effect
if (effectSettled) return;
effectSettled = true;
/**
propagates cancel downward
catch uncaught cancellations errors,
because w'll throw our own cancellation error inside this generator
**/
try {
currCb.cancel(cancelError);
} catch (err) {
void 0;
}
currCb.cancel = _utils.noop; // defensive measure
/**
triggers/propagates the cancellation error
**/
cb(cancelError);
monitor(monitorActions.effectRejected(effectId, cancelError));
};
def.promise.then(function (result) {
return monitor(monitorActions.effectResolved(effectId, result));
/**
each effect runner must attach its own logic of cancellation to the provided callback
it allows this generator to propagate cancellation downward.
ATTENTION! effect runners must setup the cancel logic by setting cb.cancel = [cancelMethod]
And the setup must occur before calling the callback
This is a sort of inversion of control: called async functions are responsible
of completing the flow by calling the provided continuation; while caller functions
are responsible for aborting the current flow by calling the attached cancel function
Library users can attach their own cancellation logic to promises by defining a
promise[CANCEL] method in their returned promises
ATTENTION! calling cancel must have no effect on an already completed or cancelled effect
**/
var data = undefined;
return(
// Non declarative effect
_utils.is.promise(effect) ? resolvePromise(effect, currCb) : _utils.is.iterator(effect) ? resolveIterator(effect, effectId, name, currCb)
// declarative effects
: _utils.is.array(effect) ? runParallelEffect(effect, effectId, currCb) : _utils.is.notUndef(data = _io.as.take(effect)) ? runTakeEffect(data, currCb) : _utils.is.notUndef(data = _io.as.put(effect)) ? runPutEffect(data, currCb) : _utils.is.notUndef(data = _io.as.race(effect)) ? runRaceEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.as.call(effect)) ? runCallEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.as.cps(effect)) ? runCPSEffect(data, currCb) : _utils.is.notUndef(data = _io.as.fork(effect)) ? runForkEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.as.join(effect)) ? runJoinEffect(data, currCb) : _utils.is.notUndef(data = _io.as.cancel(effect)) ? runCancelEffect(data, currCb) : /* anything else returned as is */currCb(null, effect)
);
}
function resolvePromise(promise, cb) {
var cancelPromise = promise[CANCEL];
if (typeof cancelPromise === 'function') {
cb.cancel = cancelPromise;
}
promise.then(function (result) {
return cb(null, result);
}, function (error) {
return monitor(monitorActions.effectRejected(effectId, error));
return cb(error);
});
return def.promise;
}
function runTakeEffect(pattern) {
var def = (0, _utils.deferred)({ match: (0, _io.matcher)(pattern), pattern: pattern });
function resolveIterator(iterator, effectId, name, cb) {
resolvePromise(proc(iterator, subscribe, dispatch, monitor, effectId, name).done, cb);
}
function runTakeEffect(pattern, cb) {
var def = {
match: (0, _io.matcher)(pattern),
pattern: pattern,
resolve: function resolve(input) {
return cb(null, input);
}
};
deferredInputs.push(def);
var done = function done() {
// cancellation logic for take effect
cb.cancel = function () {
return (0, _utils.remove)(deferredInputs, def);
};
def.promise.then(done, done);
def.promise[CANCEL] = done;
return def.promise;
}
function runPutEffect(action) {
return (0, _utils.asap)(function () {
return dispatch(action);
function runPutEffect(action, cb) {
// TODO check why synchronously nested dispatches aren't forwarded to the store
// For now, this workaround allows the dispatch to occur on the next microtask
// But could have side effect on a sync interleaved take/dispatch flow (ARGGHHHHHHH)
(0, _utils.asap)(function () {
return cb(null, dispatch(action));
});
// Put effects are non cancellables
}
function runCallEffect(_ref2, effectId) {
function runCallEffect(_ref2, effectId, cb) {
var context = _ref2.context;

@@ -465,6 +611,6 @@ var fn = _ref2.fn;

var result = fn.apply(context, args);
return !_utils.is.iterator(result) ? Promise.resolve(result) : proc(result, subscribe, dispatch, monitor, effectId, fn.name).done;
return _utils.is.promise(result) ? resolvePromise(result, cb) : _utils.is.iterator(result) ? resolveIterator(result, effectId, fn.name, cb) : cb(null, result);
}
function runCPSEffect(_ref3) {
function runCPSEffect(_ref3, cb) {
var context = _ref3.context;

@@ -474,10 +620,8 @@ var fn = _ref3.fn;

return new Promise(function (resolve, reject) {
fn.apply(context, args.concat(function (err, res) {
return _utils.is.undef(err) ? resolve(res) : reject(err);
}));
});
// CPS (ie node style functions) can define their own cancellation logic
// by setting cancel field on the cb
fn.apply(context, args.concat(cb));
}
function runForkEffect(_ref4, effectId) {
function runForkEffect(_ref4, effectId, cb) {
var context = _ref4.context;

@@ -521,75 +665,168 @@ var fn = _ref4.fn;

return Promise.resolve(proc(_iterator, subscribe, dispatch, monitor, effectId, fn.name, true));
cb(null, proc(_iterator, subscribe, dispatch, monitor, effectId, fn.name, true));
// Fork effects are non cancellables
}
function runJoinEffect(task) {
return task.done;
function runJoinEffect(task, cb) {
resolvePromise(task.done, cb);
}
function runCancelEffect(task) {
task.done[CANCEL](new SagaCancellationException(MANUAL_CANCEL, '', name));
return Promise.resolve();
function runCancelEffect(task, cb) {
// cancel the given task
// uncaught cancellations errors bubbles upward
task.done[CANCEL](new _SagaCancellationException2.default(MANUAL_CANCEL, name, name));
cb();
// cancel effects are non cancellables
}
function runParallelEffect(effects, effectId) {
var promises = effects.map(function (eff) {
return runEffect(eff, effectId);
// Reimplementing Promise.all. We're in 2016
function runParallelEffect(effects, effectId, cb) {
var completedCount = 0;
var completed = undefined;
var results = Array(effects.length);
var childCbs = effects.map(function (eff, idx) {
var chCbAtIdx = function chCbAtIdx(err, res) {
// Either we've been cancelled, or an error aborted the whole effect
if (completed) return;
// one of the effects failed
if (err) {
// cancel all other effects
// This is an AUTO_CANCEL (not triggered by a manual cancel)
// Catch uncaught cancellation errors, because w'll only throw the actual
// rejection error (err) inside this generator
try {
cb.cancel(new _SagaCancellationException2.default(PARALLEL_AUTO_CANCEL, name, name));
} catch (err) {
void 0;
}
cb(err);
} else {
results[idx] = res;
completedCount++;
if (completedCount === results.length) {
completed = true;
cb(null, results);
}
}
};
chCbAtIdx.cancel = _utils.noop;
return chCbAtIdx;
});
var ret = Promise.all(promises);
ret[CANCEL] = function (error) {
promises.forEach(function (p) {
return cancelPromise(p, error);
});
// This is different, a cancellation coming from upward
// either a MANUAL_CANCEL or a parent AUTO_CANCEL
// No need to catch, will be swallowed by the caller
cb.cancel = function (cancelError) {
// prevents unnecessary cancellation
if (!completed) {
completed = true;
childCbs.forEach(function (chCb) {
return chCb.cancel(cancelError);
});
}
};
ret.catch(function () {
ret[CANCEL](new SagaCancellationException(PARALLEL_AUTO_CANCEL, name, name));
effects.forEach(function (eff, idx) {
return runEffect(eff, effectId, idx, childCbs[idx]);
});
return ret;
}
function runRaceEffect(effects, effectId) {
var promises = [];
var retP = Promise.race(Object.keys(effects).map(function (key) {
var promise = runEffect(effects[key], effectId, key);
promises.push(promise);
return promise.then(function (result) {
return _defineProperty({}, key, result);
}, function (error) {
return Promise.reject(_defineProperty({}, key, error));
});
}));
// And yet; Promise.race
function runRaceEffect(effects, effectId, cb) {
var completed = undefined;
var keys = Object.keys(effects);
var childCbs = {};
retP[CANCEL] = function (error) {
promises.forEach(function (p) {
return cancelPromise(p, error);
});
};
keys.forEach(function (key) {
var chCbAtKey = function chCbAtKey(err, res) {
// Either we've been cancelled, or an error aborted the whole effect
if (completed) return;
var done = function done() {
return retP[CANCEL](new SagaCancellationException(RACE_AUTO_CANCEL, name, name));
if (err) {
// Race Auto cancellation
try {
cb.cancel(new _SagaCancellationException2.default(RACE_AUTO_CANCEL, name, name));
} catch (err) {
void 0;
}
cb(_defineProperty({}, key, err));
} else {
try {
cb.cancel(new _SagaCancellationException2.default(RACE_AUTO_CANCEL, name, name));
} catch (err) {
void 0;
}
completed = true;
cb(null, _defineProperty({}, key, res));
}
};
chCbAtKey.cancel = _utils.noop;
childCbs[key] = chCbAtKey;
});
cb.cancel = function (cancelError) {
// prevents unnecessary cancellation
if (!completed) {
completed = true;
keys.forEach(function (key) {
return childCbs[key].cancel(cancelError);
});
}
};
retP.then(done, done);
return retP;
keys.forEach(function (key) {
return runEffect(effects[key], effectId, key, childCbs[key]);
});
}
function newTask(id, name, iterator, done, forked) {
var _ref6;
var _ref5;
return _ref6 = {}, _defineProperty(_ref6, _utils.TASK, true), _defineProperty(_ref6, 'id', id), _defineProperty(_ref6, 'name', name), _defineProperty(_ref6, 'done', done), _defineProperty(_ref6, 'forked', forked), _defineProperty(_ref6, 'isRunning', function isRunning() {
return _ref5 = {}, _defineProperty(_ref5, _utils.TASK, true), _defineProperty(_ref5, 'id', id), _defineProperty(_ref5, 'name', name), _defineProperty(_ref5, 'done', done), _defineProperty(_ref5, 'forked', forked), _defineProperty(_ref5, 'isRunning', function isRunning() {
return iterator._isRunning;
}), _defineProperty(_ref6, 'getResult', function getResult() {
}), _defineProperty(_ref5, 'getResult', function getResult() {
return iterator._result;
}), _defineProperty(_ref6, 'getError', function getError() {
}), _defineProperty(_ref5, 'getError', function getError() {
return iterator._error;
}), _ref6;
}), _ref5;
}
}
function cancelPromise(promise, error) {
if (promise[CANCEL]) promise[CANCEL](error);
}
/***/ },
/* 4 */
/***/ function(module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = SagaCancellationException;
/**
* Creates an instance of a cancellation error
* used internally by the Library to handle Cancellations effects
* params:
* type: PARALLEL_AUTO_CANCEL | RACE_AUTO_CANCEL | MANUAL_CANCEL
* saga: current saga where the cancellation is to be thrown
* origin: Origin saga from which the cancellation originated
*/
function SagaCancellationException(type, saga, origin) {
var message = 'SagaCancellationException; type: ' + type + ', saga: ' + saga + ', origin: ' + origin;
this.name = 'SagaCancellationException';
this.message = message;
this.type = type;
this.saga = saga;
this.origin = origin;
this.stack = new Error().stack;
}
SagaCancellationException.prototype = Object.create(Error.prototype);
SagaCancellationException.prototype.constructor = SagaCancellationException;
/***/ },
/* 3 */
/* 5 */
/***/ function(module, exports, __webpack_require__) {

@@ -630,3 +867,3 @@

/***/ },
/* 4 */
/* 6 */
/***/ function(module, exports, __webpack_require__) {

@@ -817,40 +1054,3 @@

/***/ },
/* 5 */
/***/ function(module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.effectTriggered = effectTriggered;
exports.effectResolved = effectResolved;
exports.effectRejected = effectRejected;
var EFFECT_TRIGGERED = exports.EFFECT_TRIGGERED = 'EFFECT_TRIGGERED';
var EFFECT_RESOLVED = exports.EFFECT_RESOLVED = 'EFFECT_RESOLVED';
var EFFECT_REJECTED = exports.EFFECT_REJECTED = 'EFFECT_REJECTED';
function effectTriggered(effectId, parentEffectId, label, effect) {
return {
type: EFFECT_TRIGGERED,
effectId: effectId, parentEffectId: parentEffectId, label: label, effect: effect
};
}
function effectResolved(effectId, result) {
return {
type: EFFECT_RESOLVED,
effectId: effectId, result: result
};
}
function effectRejected(effectId, error) {
return {
type: EFFECT_REJECTED,
effectId: effectId, error: error
};
}
/***/ },
/* 6 */
/* 7 */
/***/ function(module, exports, __webpack_require__) {

@@ -866,10 +1066,12 @@

var _proc = __webpack_require__(2);
var _proc = __webpack_require__(3);
var _proc2 = _interopRequireDefault(_proc);
var _emitter = __webpack_require__(3);
var _emitter = __webpack_require__(5);
var _emitter2 = _interopRequireDefault(_emitter);
var _monitorActions = __webpack_require__(2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -887,9 +1089,10 @@

var sagaEmitter = (0, _emitter2.default)();
var monitor = _utils.isDev ? function (action) {
return (0, _utils.asap)(function () {
return dispatch(action);
});
} : undefined;
sagas.forEach(function (saga) {
(0, _proc2.default)(saga(getState), sagaEmitter.subscribe, dispatch, function (action) {
return (0, _utils.asap)(function () {
return dispatch(action);
});
}, 0, saga.name);
(0, _proc2.default)(saga(getState), sagaEmitter.subscribe, dispatch, monitor, 0, saga.name);
});

@@ -900,3 +1103,5 @@

var result = next(action); // hit reducers
sagaEmitter.emit(action);
// filter out monitor actions to avoid endless loop
// see https://github.com/yelouafi/redux-saga/issues/61
if (!action[_monitorActions.MONITOR_ACTION]) sagaEmitter.emit(action);
return result;

@@ -909,3 +1114,3 @@ };

/***/ },
/* 7 */
/* 8 */
/***/ function(module, exports, __webpack_require__) {

@@ -924,7 +1129,7 @@

var _proc = __webpack_require__(2);
var _proc = __webpack_require__(3);
var _proc2 = _interopRequireDefault(_proc);
var _emitter = __webpack_require__(3);
var _emitter = __webpack_require__(5);

@@ -972,2 +1177,99 @@ var _emitter2 = _interopRequireDefault(_emitter);

/***/ },
/* 9 */
/***/ function(module, exports) {
// shim for using process in browser
var process = module.exports = {};
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = setTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
clearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
setTimeout(drainQueue, 0);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
/***/ }

@@ -974,0 +1276,0 @@ /******/ ])

@@ -1,1 +0,1 @@

!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.ReduxSaga=n():e.ReduxSaga=n()}(this,function(){return function(e){function n(t){if(r[t])return r[t].exports;var u=r[t]={exports:{},id:t,loaded:!1};return e[t].call(u.exports,u,u.exports,n),u.loaded=!0,u.exports}var r={};return n.m=e,n.c=r,n.p="",n(0)}([function(e,n,r){"use strict";function t(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n.default=e,n}function u(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(n,"__esModule",{value:!0}),n.monitorActions=n.storeIO=n.runSaga=n.as=n.cancel=n.join=n.fork=n.cps=n.apply=n.call=n.race=n.put=n.take=n.is=n.MANUAL_CANCEL=n.PARALLEL_AUTO_CANCEL=n.RACE_AUTO_CANCEL=n.SagaCancellationException=void 0;var o=r(2);Object.defineProperty(n,"SagaCancellationException",{enumerable:!0,get:function(){return o.SagaCancellationException}}),Object.defineProperty(n,"RACE_AUTO_CANCEL",{enumerable:!0,get:function(){return o.RACE_AUTO_CANCEL}}),Object.defineProperty(n,"PARALLEL_AUTO_CANCEL",{enumerable:!0,get:function(){return o.PARALLEL_AUTO_CANCEL}}),Object.defineProperty(n,"MANUAL_CANCEL",{enumerable:!0,get:function(){return o.MANUAL_CANCEL}});var a=r(1);Object.defineProperty(n,"is",{enumerable:!0,get:function(){return a.is}});var i=r(4);Object.defineProperty(n,"take",{enumerable:!0,get:function(){return i.take}}),Object.defineProperty(n,"put",{enumerable:!0,get:function(){return i.put}}),Object.defineProperty(n,"race",{enumerable:!0,get:function(){return i.race}}),Object.defineProperty(n,"call",{enumerable:!0,get:function(){return i.call}}),Object.defineProperty(n,"apply",{enumerable:!0,get:function(){return i.apply}}),Object.defineProperty(n,"cps",{enumerable:!0,get:function(){return i.cps}}),Object.defineProperty(n,"fork",{enumerable:!0,get:function(){return i.fork}}),Object.defineProperty(n,"join",{enumerable:!0,get:function(){return i.join}}),Object.defineProperty(n,"cancel",{enumerable:!0,get:function(){return i.cancel}}),Object.defineProperty(n,"as",{enumerable:!0,get:function(){return i.as}});var c=r(7);Object.defineProperty(n,"runSaga",{enumerable:!0,get:function(){return c.runSaga}}),Object.defineProperty(n,"storeIO",{enumerable:!0,get:function(){return c.storeIO}});var f=r(6),s=u(f),l=r(5),d=t(l);n.default=s.default,n.monitorActions=d},function(e,n){"use strict";function r(e,n,r){if(!n(e))throw new Error(r)}function t(e,n){var r=e.indexOf(n);r>=0&&e.splice(r,1)}function u(){var e=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=c({},e),r=new Promise(function(e,r){n.resolve=e,n.reject=r});return n.promise=r,n}function o(e){for(var n=[],r=0;e>r;r++)n.push(u());return n}function a(){var e=arguments.length<=0||void 0===arguments[0]?0:arguments[0];return function(){return++e}}function i(e){return Promise.resolve(1).then(function(){return e()})}var c=Object.assign||function(e){for(var n=1;n<arguments.length;n++){var r=arguments[n];for(var t in r)Object.prototype.hasOwnProperty.call(r,t)&&(e[t]=r[t])}return e};Object.defineProperty(n,"__esModule",{value:!0}),n.check=r,n.remove=t,n.deferred=u,n.arrayOfDeffered=o,n.autoInc=a,n.asap=i;var f=n.TASK=Symbol("TASK"),s=(n.kTrue=function(){return!0},n.noop=function(){},n.is={undef:function(e){return null===e||void 0===e},notUndef:function(e){return null!==e&&void 0!==e},func:function(e){return"function"==typeof e},array:Array.isArray,promise:function(e){return e&&s.func(e.then)},iterator:function(e){return e&&s.func(e.next)&&s.func(e[Symbol.iterator])},"throw":function(e){return e&&s.func(e.throw)},task:function(e){return e&&e[f]}})},function(e,n,r){"use strict";function t(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n.default=e,n}function u(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function o(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}function a(e){function n(u,o){if(e._isRunning)try{if(o&&!x)throw u;var a=o?e.throw(u):e.next(u);if(a.done)r(a.value);else{var i=t(a.value,N);I.promise[v]=i[v],i.then(n,function(e){return n(e,!0)})}}catch(c){console.warn(w+": uncaught",c),r(c,!0)}}function r(n,r){e._isRunning=!1,r?(e._error=n,I.reject(n)):(e._result=n,I.resolve(n)),S()}function t(e,n){var r=arguments.length<=2||void 0===arguments[2]?"":arguments[2],t=g();P(s.effectTriggered(t,n,r,e));var u=void 0,l=i.is.array(e)?y(e,t):i.is.iterator(e)?a(e,T,j,P,t).done:(u=c.as.take(e))?o(u):(u=c.as.put(e))?f(u):(u=c.as.race(e))?h(u,t):(u=c.as.call(e))?E(u,t):(u=c.as.cps(e))?_(u):(u=c.as.fork(e))?R(u,t):(u=c.as.join(e))?b(u):(u=c.as.cancel(e))?O(u):Promise.resolve(e),d=(0,i.deferred)(),p=!0,m=function(e){return function(n){p&&(p=!1,e(n))}};return l.then(m(d.resolve),m(d.reject)),d.promise[v]=function(e){var n=e.type,r=e.origin;if(p){p=!1;var t=new A(n,w,r);L(l,t),d.reject(t)}},d.promise.then(function(e){return P(s.effectResolved(t,e))},function(e){return P(s.effectRejected(t,e))}),d.promise}function o(e){var n=(0,i.deferred)({match:(0,c.matcher)(e),pattern:e});k.push(n);var r=function(){return(0,i.remove)(k,n)};return n.promise.then(r,r),n.promise[v]=r,n.promise}function f(e){return(0,i.asap)(function(){return j(e)})}function E(e,n){var r=e.context,t=e.fn,u=e.args,o=t.apply(r,u);return i.is.iterator(o)?a(o,T,j,P,n,t.name).done:Promise.resolve(o)}function _(e){var n=e.context,r=e.fn,t=e.args;return new Promise(function(e,u){r.apply(n,t.concat(function(n,r){return i.is.undef(n)?e(r):u(n)}))})}function R(e,n){var r=e.context,t=e.fn,u=e.args,o=void 0,c=void 0;return o=t.apply(r,u),c=i.is.iterator(o)?o:regeneratorRuntime.mark(function f(){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,o;case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}},f,this)})(),Promise.resolve(a(c,T,j,P,n,t.name,!0))}function b(e){return e.done}function O(e){return e.done[v](new A(m,"",w)),Promise.resolve()}function y(e,n){var r=e.map(function(e){return t(e,n)}),u=Promise.all(r);return u[v]=function(e){r.forEach(function(n){return L(n,e)})},u.catch(function(){u[v](new A(d,w,w))}),u}function h(e,n){var r=[],o=Promise.race(Object.keys(e).map(function(o){var a=t(e[o],n,o);return r.push(a),a.then(function(e){return u({},o,e)},function(e){return Promise.reject(u({},o,e))})}));o[v]=function(e){r.forEach(function(n){return L(n,e)})};var a=function(){return o[v](new A(p,w,w))};return o.then(a,a),o}function C(e,n,r,t,o){var a;return a={},u(a,i.TASK,!0),u(a,"id",e),u(a,"name",n),u(a,"done",t),u(a,"forked",o),u(a,"isRunning",function(){return r._isRunning}),u(a,"getResult",function(){return r._result}),u(a,"getError",function(){return r._error}),a}function L(e,n){e[v]&&e[v](n)}var T=arguments.length<=1||void 0===arguments[1]?function(){return i.noop}:arguments[1],j=arguments.length<=2||void 0===arguments[2]?i.noop:arguments[2],P=arguments.length<=3||void 0===arguments[3]?i.noop:arguments[3],N=arguments.length<=4||void 0===arguments[4]?0:arguments[4],w=arguments.length<=5||void 0===arguments[5]?"anonymous":arguments[5];(0,i.check)(e,i.is.iterator,l);var k=[],x=i.is.throw(e),I=(0,i.deferred)(),S=T(function(e){k.forEach(function(n){n.match(e)&&n.resolve(e)})});return e._isRunning=!0,n(),C(N,w,e,I.promise)}Object.defineProperty(n,"__esModule",{value:!0}),n.SagaCancellationException=n.CANCEL=n.MANUAL_CANCEL=n.RACE_AUTO_CANCEL=n.PARALLEL_AUTO_CANCEL=n.NOT_ITERATOR_ERROR=void 0,n.default=a;var i=r(1),c=r(4),f=r(5),s=t(f),l=n.NOT_ITERATOR_ERROR="proc first argument (Saga function result) must be an iterator",d=n.PARALLEL_AUTO_CANCEL="PARALLEL_AUTO_CANCEL",p=n.RACE_AUTO_CANCEL="RACE_AUTO_CANCEL",m=n.MANUAL_CANCEL="MANUAL_CANCEL",g=(0,i.autoInc)(),v=n.CANCEL=Symbol("@@redux-saga/cancelPromise"),A=n.SagaCancellationException=function E(e,n,r){o(this,E),this.type=e,this.saga=n,this.origin=r}},function(e,n,r){"use strict";function t(){function e(e){return r.push(e),function(){return(0,u.remove)(r,e)}}function n(e){r.slice().forEach(function(n){return n(e)})}var r=[];return{subscribe:e,emit:n}}Object.defineProperty(n,"__esModule",{value:!0}),n.default=t;var u=r(1)},function(e,n,r){"use strict";function t(e,n,r){return n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r,e}function u(e){return("*"===e?w.wildcard:v.is.array(e)?w.array:v.is.func(e)?w.predicate:w.default)(e)}function o(e){if(arguments.length>0&&v.is.undef(e))throw new Error(R);return N(O,v.is.undef(e)?"*":e)}function a(e){return N(y,e)}function i(e){return N(h,e)}function c(e,n){(0,v.check)(e,v.is.notUndef,A);var r=null;if(v.is.array(e)){var t=e,u=g(t,2);r=u[0],e=u[1]}else if(e.fn){var o=e;r=o.context,e=o.fn}return(0,v.check)(e,v.is.func,A),{context:r,fn:e,args:n}}function f(e){for(var n=arguments.length,r=Array(n>1?n-1:0),t=1;n>t;t++)r[t-1]=arguments[t];return N(C,c(e,r))}function s(e,n){var r=arguments.length<=2||void 0===arguments[2]?[]:arguments[2];return N(C,c({context:e,fn:n},r))}function l(e){for(var n=arguments.length,r=Array(n>1?n-1:0),t=1;n>t;t++)r[t-1]=arguments[t];return N(L,c(e,r))}function d(e){for(var n=arguments.length,r=Array(n>1?n-1:0),t=1;n>t;t++)r[t-1]=arguments[t];return N(T,c(e,r))}function p(e){if(!k(e))throw new Error(E);return N(j,e)}function m(e){if(!k(e))throw new Error(_);return N(P,e)}var g=function(){function e(e,n){var r=[],t=!0,u=!1,o=void 0;try{for(var a,i=e[Symbol.iterator]();!(t=(a=i.next()).done)&&(r.push(a.value),!n||r.length!==n);t=!0);}catch(c){u=!0,o=c}finally{try{!t&&i.return&&i.return()}finally{if(u)throw o}}return r}return function(n,r){if(Array.isArray(n))return n;if(Symbol.iterator in Object(n))return e(n,r);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();Object.defineProperty(n,"__esModule",{value:!0}),n.as=n.INVALID_PATTERN=n.CANCEL_ARG_ERROR=n.JOIN_ARG_ERROR=n.FORK_ARG_ERROR=n.CALL_FUNCTION_ARG_ERROR=void 0,n.matcher=u,n.take=o,n.put=a,n.race=i,n.call=f,n.apply=s,n.cps=l,n.fork=d,n.join=p,n.cancel=m;var v=r(1),A=n.CALL_FUNCTION_ARG_ERROR="call/cps/fork first argument must be a function, an array [context, function] or an object {context, fn}",E=(n.FORK_ARG_ERROR="fork first argument must be a generator function or an iterator",n.JOIN_ARG_ERROR="join argument must be a valid task (a result of a fork)"),_=n.CANCEL_ARG_ERROR="cancel argument must be a valid task (a result of a fork)",R=n.INVALID_PATTERN="Invalid pattern passed to `take` (HINT: check if you didn't mispell a constant)",b=Symbol("IO"),O="TAKE",y="PUT",h="RACE",C="CALL",L="CPS",T="FORK",j="JOIN",P="CANCEL",N=function(e,n){var r;return r={},t(r,b,!0),t(r,e,n),r},w={wildcard:function(){return v.kTrue},"default":function(e){return function(n){return n.type===e}},array:function(e){return function(n){return e.some(function(e){return e===n.type})}},predicate:function(e){return function(n){return e(n)}}},k=function(e){return e[v.TASK]};n.as={take:function(e){return e&&e[b]&&e[O]},put:function(e){return e&&e[b]&&e[y]},race:function(e){return e&&e[b]&&e[h]},call:function(e){return e&&e[b]&&e[C]},cps:function(e){return e&&e[b]&&e[L]},fork:function(e){return e&&e[b]&&e[T]},join:function(e){return e&&e[b]&&e[j]},cancel:function(e){return e&&e[b]&&e[P]}}},function(e,n){"use strict";function r(e,n,r,t){return{type:o,effectId:e,parentEffectId:n,label:r,effect:t}}function t(e,n){return{type:a,effectId:e,result:n}}function u(e,n){return{type:i,effectId:e,error:n}}Object.defineProperty(n,"__esModule",{value:!0}),n.effectTriggered=r,n.effectResolved=t,n.effectRejected=u;var o=n.EFFECT_TRIGGERED="EFFECT_TRIGGERED",a=n.EFFECT_RESOLVED="EFFECT_RESOLVED",i=n.EFFECT_REJECTED="EFFECT_REJECTED"},function(e,n,r){"use strict";function t(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(n,"__esModule",{value:!0});var u=r(1),o=r(2),a=t(o),i=r(3),c=t(i);n.default=function(){for(var e=arguments.length,n=Array(e),r=0;e>r;r++)n[r]=arguments[r];return function(e){var r=e.getState,t=e.dispatch,o=(0,c.default)();return n.forEach(function(e){(0,a.default)(e(r),o.subscribe,t,function(e){return(0,u.asap)(function(){return t(e)})},0,e.name)}),function(e){return function(n){var r=e(n);return o.emit(n),r}}}}},function(e,n,r){"use strict";function t(e){return e&&e.__esModule?e:{"default":e}}function u(e){if(e[d])return e[d];var n=(0,s.default)(),r=e.dispatch;return e.dispatch=function(e){var t=r(e);return n.emit(e),t},e[d]={subscribe:n.subscribe,dispatch:e.dispatch},e[d]}function o(e,n){var r=n.subscribe,t=n.dispatch,u=arguments.length<=2||void 0===arguments[2]?a.noop:arguments[2];return(0,a.check)(e,a.is.iterator,l),(0,c.default)(e,r,t,u)}Object.defineProperty(n,"__esModule",{value:!0}),n.NOT_ITERATOR_ERROR=void 0,n.storeIO=u,n.runSaga=o;var a=r(1),i=r(2),c=t(i),f=r(3),s=t(f),l=n.NOT_ITERATOR_ERROR="runSaga must be called on an iterator",d=Symbol("IO")}])});
!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.ReduxSaga=n():e.ReduxSaga=n()}(this,function(){return function(e){function n(r){if(t[r])return t[r].exports;var u=t[r]={exports:{},id:r,loaded:!1};return e[r].call(u.exports,u,u.exports,n),u.loaded=!0,u.exports}var t={};return n.m=e,n.c=t,n.p="",n(0)}([function(e,n,t){"use strict";function r(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[t]=e[t]);return n.default=e,n}function u(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(n,"__esModule",{value:!0}),n.monitorActions=n.storeIO=n.runSaga=n.as=n.cancel=n.join=n.fork=n.cps=n.apply=n.call=n.race=n.put=n.take=n.is=n.SagaCancellationException=n.MANUAL_CANCEL=n.PARALLEL_AUTO_CANCEL=n.RACE_AUTO_CANCEL=n.CANCEL=void 0;var o=t(3);Object.defineProperty(n,"CANCEL",{enumerable:!0,get:function(){return o.CANCEL}}),Object.defineProperty(n,"RACE_AUTO_CANCEL",{enumerable:!0,get:function(){return o.RACE_AUTO_CANCEL}}),Object.defineProperty(n,"PARALLEL_AUTO_CANCEL",{enumerable:!0,get:function(){return o.PARALLEL_AUTO_CANCEL}}),Object.defineProperty(n,"MANUAL_CANCEL",{enumerable:!0,get:function(){return o.MANUAL_CANCEL}});var a=t(1);Object.defineProperty(n,"is",{enumerable:!0,get:function(){return a.is}});var i=t(6);Object.defineProperty(n,"take",{enumerable:!0,get:function(){return i.take}}),Object.defineProperty(n,"put",{enumerable:!0,get:function(){return i.put}}),Object.defineProperty(n,"race",{enumerable:!0,get:function(){return i.race}}),Object.defineProperty(n,"call",{enumerable:!0,get:function(){return i.call}}),Object.defineProperty(n,"apply",{enumerable:!0,get:function(){return i.apply}}),Object.defineProperty(n,"cps",{enumerable:!0,get:function(){return i.cps}}),Object.defineProperty(n,"fork",{enumerable:!0,get:function(){return i.fork}}),Object.defineProperty(n,"join",{enumerable:!0,get:function(){return i.join}}),Object.defineProperty(n,"cancel",{enumerable:!0,get:function(){return i.cancel}}),Object.defineProperty(n,"as",{enumerable:!0,get:function(){return i.as}});var c=t(8);Object.defineProperty(n,"runSaga",{enumerable:!0,get:function(){return c.runSaga}}),Object.defineProperty(n,"storeIO",{enumerable:!0,get:function(){return c.storeIO}});var f=t(7),s=u(f),l=t(4),d=u(l),p=t(2),g=r(p);n.default=s.default;n.SagaCancellationException=d.default;n.monitorActions=g},function(e,n,t){(function(e){"use strict";function t(e,n,t){if(!n(e))throw new Error(t)}function r(e,n){var t=e.indexOf(n);t>=0&&e.splice(t,1)}function u(){var e=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=c({},e),t=new Promise(function(e,t){n.resolve=e,n.reject=t});return n.promise=t,n}function o(e){for(var n=[],t=0;e>t;t++)n.push(u());return n}function a(){var e=arguments.length<=0||void 0===arguments[0]?0:arguments[0];return function(){return++e}}function i(e){return Promise.resolve(1).then(function(){return e()})}var c=Object.assign||function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])}return e};Object.defineProperty(n,"__esModule",{value:!0}),n.check=t,n.remove=r,n.deferred=u,n.arrayOfDeffered=o,n.autoInc=a,n.asap=i;var f=n.TASK=Symbol("TASK"),s=(n.kTrue=function(){return!0},n.noop=function(){},n.isDev="undefined"!=typeof e&&e.env&&!1,n.is={undef:function(e){return null===e||void 0===e},notUndef:function(e){return null!==e&&void 0!==e},func:function(e){return"function"==typeof e},array:Array.isArray,promise:function(e){return e&&s.func(e.then)},iterator:function(e){return e&&s.func(e.next)&&s.func(e[Symbol.iterator])},"throw":function(e){return e&&s.func(e.throw)},task:function(e){return e&&e[f]}})}).call(n,t(9))},function(e,n){"use strict";function t(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function r(e,n,r,u){var o;return o={},t(o,a,!0),t(o,"type",i),t(o,"effectId",e),t(o,"parentEffectId",n),t(o,"label",r),t(o,"effect",u),o}function u(e,n){var r;return r={},t(r,a,!0),t(r,"type",c),t(r,"effectId",e),t(r,"result",n),r}function o(e,n){var r;return r={},t(r,a,!0),t(r,"type",f),t(r,"effectId",e),t(r,"error",n),r}Object.defineProperty(n,"__esModule",{value:!0}),n.effectTriggered=r,n.effectResolved=u,n.effectRejected=o;var a=n.MONITOR_ACTION="MONITOR_ACTION",i=n.EFFECT_TRIGGERED="EFFECT_TRIGGERED",c=n.EFFECT_RESOLVED="EFFECT_RESOLVED",f=n.EFFECT_REJECTED="EFFECT_REJECTED"},function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function u(e){if(e&&e.__esModule)return e;var n={};if(null!=e)for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[t]=e[t]);return n.default=e,n}function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e){function n(u,o){if(!e._isRunning)throw new Error("Trying to resume an already finished generator");try{if(u&&!x)throw u;var a=u?e.throw(u):e.next(o);a.done?t(a.value):r(a.value,P,"",n)}catch(u){i.isDev&&console.warn(I+": uncaught",u),t(u,!0)}}function t(n,t){e._isRunning=!1,t?(e._error=n,U.reject(n)):(e._result=n,U.resolve(n)),S()}function r(e,n){function t(e,n){d||(d=!0,o.cancel=i.noop,w(e?s.effectRejected(a,e):s.effectResolved(a,n)),o(e,n))}var r=arguments.length<=2||void 0===arguments[2]?"":arguments[2],o=arguments[3],a=E();w(s.effectTriggered(a,n,r,e));var d=void 0;t.cancel=i.noop,o.cancel=function(e){if(!d){d=!0;try{t.cancel(e)}catch(n){}t.cancel=i.noop,o(e),w(s.effectRejected(a,e))}};var p=void 0;return i.is.promise(e)?u(e,t):i.is.iterator(e)?f(e,a,I,t):i.is.array(e)?C(e,a,t):i.is.notUndef(p=c.as.take(e))?l(p,t):i.is.notUndef(p=c.as.put(e))?_(p,t):i.is.notUndef(p=c.as.race(e))?L(p,a,t):i.is.notUndef(p=c.as.call(e))?y(p,a,t):i.is.notUndef(p=c.as.cps(e))?h(p,t):i.is.notUndef(p=c.as.fork(e))?O(p,a,t):i.is.notUndef(p=c.as.join(e))?b(p,t):i.is.notUndef(p=c.as.cancel(e))?R(p,t):t(null,e)}function u(e,n){var t=e[g];"function"==typeof t&&(n.cancel=t),e.then(function(e){return n(null,e)},function(e){return n(e)})}function f(e,n,t,r){u(a(e,N,j,w,n,t).done,r)}function l(e,n){var t={match:(0,c.matcher)(e),pattern:e,resolve:function(e){return n(null,e)}};k.push(t),n.cancel=function(){return(0,i.remove)(k,t)}}function _(e,n){(0,i.asap)(function(){return n(null,j(e))})}function y(e,n,t){var r=e.context,o=e.fn,a=e.args,c=o.apply(r,a);return i.is.promise(c)?u(c,t):i.is.iterator(c)?f(c,n,o.name,t):t(null,c)}function h(e,n){var t=e.context,r=e.fn,u=e.args;r.apply(t,u.concat(n))}function O(e,n,t){var r=e.context,u=e.fn,o=e.args,c=void 0,f=void 0;c=u.apply(r,o),f=i.is.iterator(c)?c:regeneratorRuntime.mark(function s(){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,c;case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}},s,this)})(),t(null,a(f,N,j,w,n,u.name,!0))}function b(e,n){u(e.done,n)}function R(e,n){e.done[g](new d.default(A,I,I)),n()}function C(e,n,t){var u=0,o=void 0,a=Array(e.length),c=e.map(function(e,n){var r=function(e,r){if(!o)if(e){try{t.cancel(new d.default(v,I,I))}catch(e){}t(e)}else a[n]=r,u++,u===a.length&&(o=!0,t(null,a))};return r.cancel=i.noop,r});t.cancel=function(e){o||(o=!0,c.forEach(function(n){return n.cancel(e)}))},e.forEach(function(e,t){return r(e,n,t,c[t])})}function L(e,n,t){var u=void 0,a=Object.keys(e),c={};a.forEach(function(e){var n=function(n,r){if(!u)if(n){try{t.cancel(new d.default(m,I,I))}catch(n){}t(o({},e,n))}else{try{t.cancel(new d.default(m,I,I))}catch(n){}u=!0,t(null,o({},e,r))}};n.cancel=i.noop,c[e]=n}),t.cancel=function(e){u||(u=!0,a.forEach(function(n){return c[n].cancel(e)}))},a.forEach(function(t){return r(e[t],n,t,c[t])})}function T(e,n,t,r,u){var a;return a={},o(a,i.TASK,!0),o(a,"id",e),o(a,"name",n),o(a,"done",r),o(a,"forked",u),o(a,"isRunning",function(){return t._isRunning}),o(a,"getResult",function(){return t._result}),o(a,"getError",function(){return t._error}),a}var N=arguments.length<=1||void 0===arguments[1]?function(){return i.noop}:arguments[1],j=arguments.length<=2||void 0===arguments[2]?i.noop:arguments[2],w=arguments.length<=3||void 0===arguments[3]?i.noop:arguments[3],P=arguments.length<=4||void 0===arguments[4]?0:arguments[4],I=arguments.length<=5||void 0===arguments[5]?"anonymous":arguments[5];(0,i.check)(e,i.is.iterator,p);var k=[],x=i.is.throw(e),U=(0,i.deferred)(),S=N(function(e){for(var n=0;n<k.length;n++){var t=k[n];t.match(e)&&(k=[],t.resolve(e))}});n.cancel=i.noop;var M=T(P,I,e,U.promise);return M.done[g]=function(e){var t=e.type,r=e.origin;n.cancel(new d.default(t,I,r))},e._isRunning=!0,n(),M}Object.defineProperty(n,"__esModule",{value:!0}),n.MANUAL_CANCEL=n.RACE_AUTO_CANCEL=n.PARALLEL_AUTO_CANCEL=n.CANCEL=n.NOT_ITERATOR_ERROR=void 0,n.default=a;var i=t(1),c=t(6),f=t(2),s=u(f),l=t(4),d=r(l),p=n.NOT_ITERATOR_ERROR="proc first argument (Saga function result) must be an iterator",g=n.CANCEL=Symbol("@@redux-saga/cancelPromise"),v=n.PARALLEL_AUTO_CANCEL="PARALLEL_AUTO_CANCEL",m=n.RACE_AUTO_CANCEL="RACE_AUTO_CANCEL",A=n.MANUAL_CANCEL="MANUAL_CANCEL",E=(0,i.autoInc)()},function(e,n){"use strict";function t(e,n,t){var r="SagaCancellationException; type: "+e+", saga: "+n+", origin: "+t;this.name="SagaCancellationException",this.message=r,this.type=e,this.saga=n,this.origin=t,this.stack=(new Error).stack}Object.defineProperty(n,"__esModule",{value:!0}),n.default=t,t.prototype=Object.create(Error.prototype),t.prototype.constructor=t},function(e,n,t){"use strict";function r(){function e(e){return t.push(e),function(){return(0,u.remove)(t,e)}}function n(e){t.slice().forEach(function(n){return n(e)})}var t=[];return{subscribe:e,emit:n}}Object.defineProperty(n,"__esModule",{value:!0}),n.default=r;var u=t(1)},function(e,n,t){"use strict";function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function u(e){return("*"===e?P.wildcard:m.is.array(e)?P.array:m.is.func(e)?P.predicate:P.default)(e)}function o(e){if(arguments.length>0&&m.is.undef(e))throw new Error(y);return w(O,m.is.undef(e)?"*":e)}function a(e){return w(b,e)}function i(e){return w(R,e)}function c(e,n){(0,m.check)(e,m.is.notUndef,A);var t=null;if(m.is.array(e)){var r=e,u=v(r,2);t=u[0],e=u[1]}else if(e.fn){var o=e;t=o.context,e=o.fn}return(0,m.check)(e,m.is.func,A),{context:t,fn:e,args:n}}function f(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];return w(C,c(e,t))}function s(e,n){var t=arguments.length<=2||void 0===arguments[2]?[]:arguments[2];return w(C,c({context:e,fn:n},t))}function l(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];return w(L,c(e,t))}function d(e){for(var n=arguments.length,t=Array(n>1?n-1:0),r=1;n>r;r++)t[r-1]=arguments[r];return w(T,c(e,t))}function p(e){if(!I(e))throw new Error(E);return w(N,e)}function g(e){if(!I(e))throw new Error(_);return w(j,e)}var v=function(){function e(e,n){var t=[],r=!0,u=!1,o=void 0;try{for(var a,i=e[Symbol.iterator]();!(r=(a=i.next()).done)&&(t.push(a.value),!n||t.length!==n);r=!0);}catch(c){u=!0,o=c}finally{try{!r&&i.return&&i.return()}finally{if(u)throw o}}return t}return function(n,t){if(Array.isArray(n))return n;if(Symbol.iterator in Object(n))return e(n,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();Object.defineProperty(n,"__esModule",{value:!0}),n.as=n.INVALID_PATTERN=n.CANCEL_ARG_ERROR=n.JOIN_ARG_ERROR=n.FORK_ARG_ERROR=n.CALL_FUNCTION_ARG_ERROR=void 0,n.matcher=u,n.take=o,n.put=a,n.race=i,n.call=f,n.apply=s,n.cps=l,n.fork=d,n.join=p,n.cancel=g;var m=t(1),A=n.CALL_FUNCTION_ARG_ERROR="call/cps/fork first argument must be a function, an array [context, function] or an object {context, fn}",E=(n.FORK_ARG_ERROR="fork first argument must be a generator function or an iterator",n.JOIN_ARG_ERROR="join argument must be a valid task (a result of a fork)"),_=n.CANCEL_ARG_ERROR="cancel argument must be a valid task (a result of a fork)",y=n.INVALID_PATTERN="Invalid pattern passed to `take` (HINT: check if you didn't mispell a constant)",h=Symbol("IO"),O="TAKE",b="PUT",R="RACE",C="CALL",L="CPS",T="FORK",N="JOIN",j="CANCEL",w=function(e,n){var t;return t={},r(t,h,!0),r(t,e,n),t},P={wildcard:function(){return m.kTrue},"default":function(e){return function(n){return n.type===e}},array:function(e){return function(n){return e.some(function(e){return e===n.type})}},predicate:function(e){return function(n){return e(n)}}},I=function(e){return e[m.TASK]};n.as={take:function(e){return e&&e[h]&&e[O]},put:function(e){return e&&e[h]&&e[b]},race:function(e){return e&&e[h]&&e[R]},call:function(e){return e&&e[h]&&e[C]},cps:function(e){return e&&e[h]&&e[L]},fork:function(e){return e&&e[h]&&e[T]},join:function(e){return e&&e[h]&&e[N]},cancel:function(e){return e&&e[h]&&e[j]}}},function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(n,"__esModule",{value:!0});var u=t(1),o=t(3),a=r(o),i=t(5),c=r(i),f=t(2);n.default=function(){for(var e=arguments.length,n=Array(e),t=0;e>t;t++)n[t]=arguments[t];return function(e){var t=e.getState,r=e.dispatch,o=(0,c.default)(),i=u.isDev?function(e){return(0,u.asap)(function(){return r(e)})}:void 0;return n.forEach(function(e){(0,a.default)(e(t),o.subscribe,r,i,0,e.name)}),function(e){return function(n){var t=e(n);return n[f.MONITOR_ACTION]||o.emit(n),t}}}}},function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{"default":e}}function u(e){if(e[d])return e[d];var n=(0,s.default)(),t=e.dispatch;return e.dispatch=function(e){var r=t(e);return n.emit(e),r},e[d]={subscribe:n.subscribe,dispatch:e.dispatch},e[d]}function o(e,n){var t=n.subscribe,r=n.dispatch,u=arguments.length<=2||void 0===arguments[2]?a.noop:arguments[2];return(0,a.check)(e,a.is.iterator,l),(0,c.default)(e,t,r,u)}Object.defineProperty(n,"__esModule",{value:!0}),n.NOT_ITERATOR_ERROR=void 0,n.storeIO=u,n.runSaga=o;var a=t(1),i=t(3),c=r(i),f=t(5),s=r(f),l=n.NOT_ITERATOR_ERROR="runSaga must be called on an iterator",d=Symbol("IO")},function(e,n){function t(){f=!1,a.length?c=a.concat(c):s=-1,c.length&&r()}function r(){if(!f){var e=setTimeout(t);f=!0;for(var n=c.length;n;){for(a=c,c=[];++s<n;)a&&a[s].run();s=-1,n=c.length}a=null,f=!1,clearTimeout(e)}}function u(e,n){this.fun=e,this.array=n}function o(){}var a,i=e.exports={},c=[],f=!1,s=-1;i.nextTick=function(e){var n=new Array(arguments.length-1);if(arguments.length>1)for(var t=1;t<arguments.length;t++)n[t-1]=arguments[t];c.push(new u(e,n)),1!==c.length||f||setTimeout(r,0)},u.prototype.run=function(){this.fun.apply(null,this.array)},i.title="browser",i.browser=!0,i.env={},i.argv=[],i.version="",i.versions={},i.on=o,i.addListener=o,i.once=o,i.off=o,i.removeListener=o,i.removeAllListeners=o,i.emit=o,i.binding=function(e){throw new Error("process.binding is not supported")},i.cwd=function(){return"/"},i.chdir=function(e){throw new Error("process.chdir is not supported")},i.umask=function(){return 0}}])});

@@ -6,10 +6,10 @@ 'use strict';

});
exports.monitorActions = exports.storeIO = exports.runSaga = exports.as = exports.cancel = exports.join = exports.fork = exports.cps = exports.apply = exports.call = exports.race = exports.put = exports.take = exports.is = exports.MANUAL_CANCEL = exports.PARALLEL_AUTO_CANCEL = exports.RACE_AUTO_CANCEL = exports.SagaCancellationException = undefined;
exports.monitorActions = exports.storeIO = exports.runSaga = exports.as = exports.cancel = exports.join = exports.fork = exports.cps = exports.apply = exports.call = exports.race = exports.put = exports.take = exports.is = exports.SagaCancellationException = exports.MANUAL_CANCEL = exports.PARALLEL_AUTO_CANCEL = exports.RACE_AUTO_CANCEL = exports.CANCEL = undefined;
var _proc = require('./proc');
Object.defineProperty(exports, 'SagaCancellationException', {
Object.defineProperty(exports, 'CANCEL', {
enumerable: true,
get: function get() {
return _proc.SagaCancellationException;
return _proc.CANCEL;
}

@@ -127,2 +127,6 @@ });

var _SagaCancellationException2 = require('./SagaCancellationException');
var _SagaCancellationException3 = _interopRequireDefault(_SagaCancellationException2);
var _monitorActions = require('./monitorActions');

@@ -137,2 +141,4 @@

exports.default = _middleware2.default;
var SagaCancellationException = exports.SagaCancellationException = _SagaCancellationException3.default;
exports.monitorActions = monitorActions;

@@ -17,2 +17,4 @@ 'use strict';

var _monitorActions = require('./monitorActions');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -30,9 +32,10 @@

var sagaEmitter = (0, _emitter2.default)();
var monitor = _utils.isDev ? function (action) {
return (0, _utils.asap)(function () {
return dispatch(action);
});
} : undefined;
sagas.forEach(function (saga) {
(0, _proc2.default)(saga(getState), sagaEmitter.subscribe, dispatch, function (action) {
return (0, _utils.asap)(function () {
return dispatch(action);
});
}, 0, saga.name);
(0, _proc2.default)(saga(getState), sagaEmitter.subscribe, dispatch, monitor, 0, saga.name);
});

@@ -43,3 +46,5 @@

var result = next(action); // hit reducers
sagaEmitter.emit(action);
// filter out monitor actions to avoid endless loop
// see https://github.com/yelouafi/redux-saga/issues/61
if (!action[_monitorActions.MONITOR_ACTION]) sagaEmitter.emit(action);
return result;

@@ -46,0 +51,0 @@ };

@@ -9,2 +9,6 @@ 'use strict';

exports.effectRejected = effectRejected;
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var MONITOR_ACTION = exports.MONITOR_ACTION = 'MONITOR_ACTION';
var EFFECT_TRIGGERED = exports.EFFECT_TRIGGERED = 'EFFECT_TRIGGERED';

@@ -15,20 +19,17 @@ var EFFECT_RESOLVED = exports.EFFECT_RESOLVED = 'EFFECT_RESOLVED';

function effectTriggered(effectId, parentEffectId, label, effect) {
return {
type: EFFECT_TRIGGERED,
effectId: effectId, parentEffectId: parentEffectId, label: label, effect: effect
};
var _ref;
return _ref = {}, _defineProperty(_ref, MONITOR_ACTION, true), _defineProperty(_ref, 'type', EFFECT_TRIGGERED), _defineProperty(_ref, 'effectId', effectId), _defineProperty(_ref, 'parentEffectId', parentEffectId), _defineProperty(_ref, 'label', label), _defineProperty(_ref, 'effect', effect), _ref;
}
function effectResolved(effectId, result) {
return {
type: EFFECT_RESOLVED,
effectId: effectId, result: result
};
var _ref2;
return _ref2 = {}, _defineProperty(_ref2, MONITOR_ACTION, true), _defineProperty(_ref2, 'type', EFFECT_RESOLVED), _defineProperty(_ref2, 'effectId', effectId), _defineProperty(_ref2, 'result', result), _ref2;
}
function effectRejected(effectId, error) {
return {
type: EFFECT_REJECTED,
effectId: effectId, error: error
};
var _ref3;
return _ref3 = {}, _defineProperty(_ref3, MONITOR_ACTION, true), _defineProperty(_ref3, 'type', EFFECT_REJECTED), _defineProperty(_ref3, 'effectId', effectId), _defineProperty(_ref3, 'error', error), _ref3;
}

@@ -6,3 +6,3 @@ 'use strict';

});
exports.SagaCancellationException = exports.CANCEL = exports.MANUAL_CANCEL = exports.RACE_AUTO_CANCEL = exports.PARALLEL_AUTO_CANCEL = exports.NOT_ITERATOR_ERROR = undefined;
exports.MANUAL_CANCEL = exports.RACE_AUTO_CANCEL = exports.PARALLEL_AUTO_CANCEL = exports.CANCEL = exports.NOT_ITERATOR_ERROR = undefined;
exports.default = proc;

@@ -18,2 +18,8 @@

var _SagaCancellationException = require('./SagaCancellationException');
var _SagaCancellationException2 = _interopRequireDefault(_SagaCancellationException);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

@@ -23,5 +29,4 @@

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var NOT_ITERATOR_ERROR = exports.NOT_ITERATOR_ERROR = 'proc first argument (Saga function result) must be an iterator';
var CANCEL = exports.CANCEL = Symbol('@@redux-saga/cancelPromise');
var PARALLEL_AUTO_CANCEL = exports.PARALLEL_AUTO_CANCEL = 'PARALLEL_AUTO_CANCEL';

@@ -33,12 +38,2 @@ var RACE_AUTO_CANCEL = exports.RACE_AUTO_CANCEL = 'RACE_AUTO_CANCEL';

var CANCEL = exports.CANCEL = Symbol('@@redux-saga/cancelPromise');
var SagaCancellationException = exports.SagaCancellationException = function SagaCancellationException(type, saga, origin) {
_classCallCheck(this, SagaCancellationException);
this.type = type;
this.saga = saga;
this.origin = origin;
};
function proc(iterator) {

@@ -55,28 +50,72 @@ var subscribe = arguments.length <= 1 || arguments[1] === undefined ? function () {

// tracks the current `take` effects
var deferredInputs = [];
var canThrow = _utils.is.throw(iterator);
// Promise to be resolved/rejected when this generator terminates (or throws)
var deferredEnd = (0, _utils.deferred)();
// subscribe to input events, this will resolve the current `take` effects
var unsubscribe = subscribe(function (input) {
deferredInputs.forEach(function (def) {
if (def.match(input)) def.resolve(input);
});
for (var i = 0; i < deferredInputs.length; i++) {
var def = deferredInputs[i];
if (def.match(input)) {
// cancel all deferredInputs; parallel takes are disallowed
// and in concurrent takes, first wins
deferredInputs = [];
def.resolve(input);
}
}
});
/**
cancel : (SagaCancellationException) -> ()
Tracks the current effect cancellation
Each time the generator progresses. calling runEffect will set a new value
on it. It allows propagating cancellation to child effects
**/
next.cancel = _utils.noop;
/**
Creates a new task descriptor for this generator
**/
var task = newTask(parentEffectId, name, iterator, deferredEnd.promise);
/**
this maybe called by a parent generator to trigger/propagate cancellation
W'll simply cancel the current effect, which will reject that effect
The rejection will throw the injected SagaCancellationException into the flow
of this generator
**/
task.done[CANCEL] = function (_ref) {
var type = _ref.type;
var origin = _ref.origin;
next.cancel(new _SagaCancellationException2.default(type, name, origin));
};
// tracks the running status
iterator._isRunning = true;
// kicks up the generator
next();
return newTask(parentEffectId, name, iterator, deferredEnd.promise);
// then return the task descriptor to the caller
return task;
function next(arg, isError) {
if (!iterator._isRunning) return;
/**
This is the generator driver
It's a recursive aysnc/continuation function which calls itself
until the generator terminates or throws
**/
function next(error, arg) {
// Preventive measure. If we endup here, then there is really something wrong
if (!iterator._isRunning) throw new Error('Trying to resume an already finished generator');
try {
if (isError && !canThrow) throw arg;
var result = isError ? iterator.throw(arg) : iterator.next(arg);
if (error && !canThrow) throw error;
// calling iterator.throw on a generator that doesnt defined a correponding try/Catch
var result = error ? iterator.throw(error) : iterator.next(arg);
if (!result.done) {
var currentEffect = runEffect(result.value, parentEffectId);
deferredEnd.promise[CANCEL] = currentEffect[CANCEL];
currentEffect.then(next, function (err) {
return next(err, true);
});
runEffect(result.value, parentEffectId, '', next);
} else {

@@ -87,3 +126,5 @@ end(result.value);

/*eslint-disable no-console*/
console.warn(name + ': uncaught', error);
if (_utils.isDev) {
console.warn(name + ': uncaught', error);
}
end(error, true);

@@ -107,2 +148,3 @@ }

var label = arguments.length <= 2 || arguments[2] === undefined ? '' : arguments[2];
var cb = arguments[3];

@@ -112,54 +154,111 @@ var effectId = nextEffectId();

var data = undefined;
var promise = _utils.is.array(effect) ? runParallelEffect(effect, effectId) : _utils.is.iterator(effect) ? proc(effect, subscribe, dispatch, monitor, effectId).done : (data = _io.as.take(effect)) ? runTakeEffect(data) : (data = _io.as.put(effect)) ? runPutEffect(data) : (data = _io.as.race(effect)) ? runRaceEffect(data, effectId) : (data = _io.as.call(effect)) ? runCallEffect(data, effectId) : (data = _io.as.cps(effect)) ? runCPSEffect(data) : (data = _io.as.fork(effect)) ? runForkEffect(data, effectId) : (data = _io.as.join(effect)) ? runJoinEffect(data) : (data = _io.as.cancel(effect)) ? runCancelEffect(data) : /* resolve anything else */Promise.resolve(effect);
/**
completion callback and cancel callback are mutually exclusive
We can't cancel an already completed effect
And We can't complete an already cancelled effectId
**/
var effectSettled = undefined;
var def = (0, _utils.deferred)();
var isRunning = true;
var completeWith = function completeWith(fn) {
return function (outcome) {
if (isRunning) {
isRunning = false;
fn(outcome);
}
};
};
promise.then(completeWith(def.resolve), completeWith(def.reject));
def.promise[CANCEL] = function (_ref) {
var type = _ref.type;
var origin = _ref.origin;
// Completion callback passed to the appropriate effect runner
function currCb(err, res) {
if (effectSettled) return;
if (isRunning) {
isRunning = false;
var error = new SagaCancellationException(type, name, origin);
cancelPromise(promise, error);
def.reject(error);
effectSettled = true;
cb.cancel = _utils.noop; // defensive measure
err ? monitor(monitorActions.effectRejected(effectId, err)) : monitor(monitorActions.effectResolved(effectId, res));
cb(err, res);
}
// tracks down the current cancel
currCb.cancel = _utils.noop;
// setup cancellation logic on the parent cb
cb.cancel = function (cancelError) {
// prevents cancelling an already completed effect
if (effectSettled) return;
effectSettled = true;
/**
propagates cancel downward
catch uncaught cancellations errors,
because w'll throw our own cancellation error inside this generator
**/
try {
currCb.cancel(cancelError);
} catch (err) {
void 0;
}
currCb.cancel = _utils.noop; // defensive measure
/**
triggers/propagates the cancellation error
**/
cb(cancelError);
monitor(monitorActions.effectRejected(effectId, cancelError));
};
def.promise.then(function (result) {
return monitor(monitorActions.effectResolved(effectId, result));
/**
each effect runner must attach its own logic of cancellation to the provided callback
it allows this generator to propagate cancellation downward.
ATTENTION! effect runners must setup the cancel logic by setting cb.cancel = [cancelMethod]
And the setup must occur before calling the callback
This is a sort of inversion of control: called async functions are responsible
of completing the flow by calling the provided continuation; while caller functions
are responsible for aborting the current flow by calling the attached cancel function
Library users can attach their own cancellation logic to promises by defining a
promise[CANCEL] method in their returned promises
ATTENTION! calling cancel must have no effect on an already completed or cancelled effect
**/
var data = undefined;
return(
// Non declarative effect
_utils.is.promise(effect) ? resolvePromise(effect, currCb) : _utils.is.iterator(effect) ? resolveIterator(effect, effectId, name, currCb)
// declarative effects
: _utils.is.array(effect) ? runParallelEffect(effect, effectId, currCb) : _utils.is.notUndef(data = _io.as.take(effect)) ? runTakeEffect(data, currCb) : _utils.is.notUndef(data = _io.as.put(effect)) ? runPutEffect(data, currCb) : _utils.is.notUndef(data = _io.as.race(effect)) ? runRaceEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.as.call(effect)) ? runCallEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.as.cps(effect)) ? runCPSEffect(data, currCb) : _utils.is.notUndef(data = _io.as.fork(effect)) ? runForkEffect(data, effectId, currCb) : _utils.is.notUndef(data = _io.as.join(effect)) ? runJoinEffect(data, currCb) : _utils.is.notUndef(data = _io.as.cancel(effect)) ? runCancelEffect(data, currCb) : /* anything else returned as is */currCb(null, effect)
);
}
function resolvePromise(promise, cb) {
var cancelPromise = promise[CANCEL];
if (typeof cancelPromise === 'function') {
cb.cancel = cancelPromise;
}
promise.then(function (result) {
return cb(null, result);
}, function (error) {
return monitor(monitorActions.effectRejected(effectId, error));
return cb(error);
});
return def.promise;
}
function runTakeEffect(pattern) {
var def = (0, _utils.deferred)({ match: (0, _io.matcher)(pattern), pattern: pattern });
function resolveIterator(iterator, effectId, name, cb) {
resolvePromise(proc(iterator, subscribe, dispatch, monitor, effectId, name).done, cb);
}
function runTakeEffect(pattern, cb) {
var def = {
match: (0, _io.matcher)(pattern),
pattern: pattern,
resolve: function resolve(input) {
return cb(null, input);
}
};
deferredInputs.push(def);
var done = function done() {
// cancellation logic for take effect
cb.cancel = function () {
return (0, _utils.remove)(deferredInputs, def);
};
def.promise.then(done, done);
def.promise[CANCEL] = done;
return def.promise;
}
function runPutEffect(action) {
return (0, _utils.asap)(function () {
return dispatch(action);
function runPutEffect(action, cb) {
// TODO check why synchronously nested dispatches aren't forwarded to the store
// For now, this workaround allows the dispatch to occur on the next microtask
// But could have side effect on a sync interleaved take/dispatch flow (ARGGHHHHHHH)
(0, _utils.asap)(function () {
return cb(null, dispatch(action));
});
// Put effects are non cancellables
}
function runCallEffect(_ref2, effectId) {
function runCallEffect(_ref2, effectId, cb) {
var context = _ref2.context;

@@ -170,6 +269,6 @@ var fn = _ref2.fn;

var result = fn.apply(context, args);
return !_utils.is.iterator(result) ? Promise.resolve(result) : proc(result, subscribe, dispatch, monitor, effectId, fn.name).done;
return _utils.is.promise(result) ? resolvePromise(result, cb) : _utils.is.iterator(result) ? resolveIterator(result, effectId, fn.name, cb) : cb(null, result);
}
function runCPSEffect(_ref3) {
function runCPSEffect(_ref3, cb) {
var context = _ref3.context;

@@ -179,10 +278,8 @@ var fn = _ref3.fn;

return new Promise(function (resolve, reject) {
fn.apply(context, args.concat(function (err, res) {
return _utils.is.undef(err) ? resolve(res) : reject(err);
}));
});
// CPS (ie node style functions) can define their own cancellation logic
// by setting cancel field on the cb
fn.apply(context, args.concat(cb));
}
function runForkEffect(_ref4, effectId) {
function runForkEffect(_ref4, effectId, cb) {
var context = _ref4.context;

@@ -226,71 +323,131 @@ var fn = _ref4.fn;

return Promise.resolve(proc(_iterator, subscribe, dispatch, monitor, effectId, fn.name, true));
cb(null, proc(_iterator, subscribe, dispatch, monitor, effectId, fn.name, true));
// Fork effects are non cancellables
}
function runJoinEffect(task) {
return task.done;
function runJoinEffect(task, cb) {
resolvePromise(task.done, cb);
}
function runCancelEffect(task) {
task.done[CANCEL](new SagaCancellationException(MANUAL_CANCEL, '', name));
return Promise.resolve();
function runCancelEffect(task, cb) {
// cancel the given task
// uncaught cancellations errors bubbles upward
task.done[CANCEL](new _SagaCancellationException2.default(MANUAL_CANCEL, name, name));
cb();
// cancel effects are non cancellables
}
function runParallelEffect(effects, effectId) {
var promises = effects.map(function (eff) {
return runEffect(eff, effectId);
// Reimplementing Promise.all. We're in 2016
function runParallelEffect(effects, effectId, cb) {
var completedCount = 0;
var completed = undefined;
var results = Array(effects.length);
var childCbs = effects.map(function (eff, idx) {
var chCbAtIdx = function chCbAtIdx(err, res) {
// Either we've been cancelled, or an error aborted the whole effect
if (completed) return;
// one of the effects failed
if (err) {
// cancel all other effects
// This is an AUTO_CANCEL (not triggered by a manual cancel)
// Catch uncaught cancellation errors, because w'll only throw the actual
// rejection error (err) inside this generator
try {
cb.cancel(new _SagaCancellationException2.default(PARALLEL_AUTO_CANCEL, name, name));
} catch (err) {
void 0;
}
cb(err);
} else {
results[idx] = res;
completedCount++;
if (completedCount === results.length) {
completed = true;
cb(null, results);
}
}
};
chCbAtIdx.cancel = _utils.noop;
return chCbAtIdx;
});
var ret = Promise.all(promises);
ret[CANCEL] = function (error) {
promises.forEach(function (p) {
return cancelPromise(p, error);
});
// This is different, a cancellation coming from upward
// either a MANUAL_CANCEL or a parent AUTO_CANCEL
// No need to catch, will be swallowed by the caller
cb.cancel = function (cancelError) {
// prevents unnecessary cancellation
if (!completed) {
completed = true;
childCbs.forEach(function (chCb) {
return chCb.cancel(cancelError);
});
}
};
ret.catch(function () {
ret[CANCEL](new SagaCancellationException(PARALLEL_AUTO_CANCEL, name, name));
effects.forEach(function (eff, idx) {
return runEffect(eff, effectId, idx, childCbs[idx]);
});
return ret;
}
function runRaceEffect(effects, effectId) {
var promises = [];
var retP = Promise.race(Object.keys(effects).map(function (key) {
var promise = runEffect(effects[key], effectId, key);
promises.push(promise);
return promise.then(function (result) {
return _defineProperty({}, key, result);
}, function (error) {
return Promise.reject(_defineProperty({}, key, error));
});
}));
// And yet; Promise.race
function runRaceEffect(effects, effectId, cb) {
var completed = undefined;
var keys = Object.keys(effects);
var childCbs = {};
retP[CANCEL] = function (error) {
promises.forEach(function (p) {
return cancelPromise(p, error);
});
};
keys.forEach(function (key) {
var chCbAtKey = function chCbAtKey(err, res) {
// Either we've been cancelled, or an error aborted the whole effect
if (completed) return;
var done = function done() {
return retP[CANCEL](new SagaCancellationException(RACE_AUTO_CANCEL, name, name));
if (err) {
// Race Auto cancellation
try {
cb.cancel(new _SagaCancellationException2.default(RACE_AUTO_CANCEL, name, name));
} catch (err) {
void 0;
}
cb(_defineProperty({}, key, err));
} else {
try {
cb.cancel(new _SagaCancellationException2.default(RACE_AUTO_CANCEL, name, name));
} catch (err) {
void 0;
}
completed = true;
cb(null, _defineProperty({}, key, res));
}
};
chCbAtKey.cancel = _utils.noop;
childCbs[key] = chCbAtKey;
});
cb.cancel = function (cancelError) {
// prevents unnecessary cancellation
if (!completed) {
completed = true;
keys.forEach(function (key) {
return childCbs[key].cancel(cancelError);
});
}
};
retP.then(done, done);
return retP;
keys.forEach(function (key) {
return runEffect(effects[key], effectId, key, childCbs[key]);
});
}
function newTask(id, name, iterator, done, forked) {
var _ref6;
var _ref5;
return _ref6 = {}, _defineProperty(_ref6, _utils.TASK, true), _defineProperty(_ref6, 'id', id), _defineProperty(_ref6, 'name', name), _defineProperty(_ref6, 'done', done), _defineProperty(_ref6, 'forked', forked), _defineProperty(_ref6, 'isRunning', function isRunning() {
return _ref5 = {}, _defineProperty(_ref5, _utils.TASK, true), _defineProperty(_ref5, 'id', id), _defineProperty(_ref5, 'name', name), _defineProperty(_ref5, 'done', done), _defineProperty(_ref5, 'forked', forked), _defineProperty(_ref5, 'isRunning', function isRunning() {
return iterator._isRunning;
}), _defineProperty(_ref6, 'getResult', function getResult() {
}), _defineProperty(_ref5, 'getResult', function getResult() {
return iterator._result;
}), _defineProperty(_ref6, 'getError', function getError() {
}), _defineProperty(_ref5, 'getError', function getError() {
return iterator._error;
}), _ref6;
}), _ref5;
}
function cancelPromise(promise, error) {
if (promise[CANCEL]) promise[CANCEL](error);
}
}

@@ -20,2 +20,4 @@ 'use strict';

var isDev = exports.isDev = typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'development';
function check(value, predicate, error) {

@@ -22,0 +24,0 @@ if (!predicate(value)) throw new Error(error);

{
"name": "redux-saga",
"version": "0.5.0",
"version": "0.6.0",
"description": "Saga middleware for Redux to handle Side Effects",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -7,3 +7,3 @@ # redux-saga

这里意外着程序逻辑会存在两个位置。
这里意味着程序逻辑会存在两个位置。

@@ -20,3 +20,3 @@ - Reducers 负责处理action的state转换

- 一个目的是抽象出 **Effect** (影响): 等待一个action,触发State更新 (使用分配action给store), 调用远程服务,这些都是不同像是的Effect。Saga使用常见的控制流程(if, while, for, try/catch)去组和这些Effect。
- 一个目的是抽象出 **Effect** (影响): 等待一个action,触发State更新 (使用分配action给store), 调用远程服务,这些都是不同形式的Effect。Saga使用常见的控制流程(if, while, for, try/catch)去组和这些Effect。

@@ -80,3 +80,3 @@ - Saga本身就是Effect。它可以通过选择器和其他Effect组合。它也可以被内部的其他Saga调用,提供丰富功能的子程序和

插入redux-sago到中间件管道
插入redux-saga到中间件管道

@@ -102,9 +102,9 @@ ```javascript

典型的, 实际的中间件处理一些Effect构成,它们会被Action创建者触发。举个例子,
典型的, 实际的中间件处理一些Effect构成,它们会被Action Creators触发。举个例子,
redux-thunk 通过调用 带 `(getState, dispatch)` 带参数的thunks来处理 *thunks* 。
redux-promise 通过调度Promise的返回值来处理Promise。redux-gen通过调用所有的迭代Action到store来处理生成器。所有这些中间件的共通是 '请求每个action'模式。当action发生的时候,他们会被一次又一次的调用。也就是说, 每次触发 *根 action*的时候, 它们都会被 *检索*。
Sagas 工作方式是不一样的,他们不是被Action创建者雇佣,但是和你的应用一起被启动,并且选择监视哪些action。它们类似于守护任务,运行在后台,并且选择他们自己的逻辑进展。在上面的例子,`incrementAsync` 使用 `yield take(...)` *拉* `INCREMENT_ASYNC` action。这是一个 *阻塞调用*, 这意味着Saga 如果没有找到匹配的action将不会推进。
Sagas 工作方式是不一样的,他们不是在Action Creators内被触发,而是随你的应用一起被启动,并且选择监视哪些action。它们类似于守护任务,运行在后台,并且选择他们自己的逻辑进展。在上面的例子,`incrementAsync` 使用 `yield take(...)` *等待* `INCREMENT_ASYNC` action。这是一个 *阻塞调用*, 这意味着Saga 如果没有找到匹配的action将不会继续执行。
上文,我们使用`take(INCREMENT_ASYNC)`的形式,它的意思是我们等待一个action它的type是`INCREMENT_ASYNC`。实际上,确切的签名是 `take(PATTERN)`, 它的模式可以下面的一种:
上文,我们使用`take(INCREMENT_ASYNC)`的形式,意思是我们等待一个type是`INCREMENT_ASYNC`的action。实际上,确切的签名是 `take(PATTERN)`, 它的模式可以下面的一种:

@@ -122,13 +122,13 @@

收到查询action之后,Saga触发器调用`delay(1000)`,在我们的例子中返回一个约定(Promise),这个将在1秒后解决。这是一个阻塞调用,所以Saga会等待一秒后再继续执行。
接收到需要的action之后,Saga触发器调用`delay(1000)`,在我们的例子中返回一个约定(Promise),这个将在1秒后解决。这是一个阻塞调用,所以Saga会等待一秒后再继续执行。
延迟之后,,Saga使用 `put(action)`函数调度 `INCREMENT_COUNTER` action。与此同时,Sago会等待调度结果。如果返回普通值,Saga立刻唤醒 *immediately*,但是如果返回值是一个约定,Sago会等待这个约定完成(或失败)。
延迟之后,Saga使用 `put(action)`函数调度 `INCREMENT_COUNTER` action。与此同时,Saga会等待调度结果。如果返回普通值,Saga立刻唤醒 *immediately*,但是如果返回值是一个Promise,Saga会等待这个Promise完成(或失败)。
#A common abstraction: Effect
概况的说,等待一个未知的action,等待像`yield delay(1000)`这样的未知的函数调用结果,或者等待一个调度的结果,这些都是相同的概念。在所有情况下,我们迭代某些形式的影响。Saga所做的,实际上就是把所有这些影响组合在一起,去实现期望的控制流。最简单的是通过把迭代一个挨着一个的执行,去顺序迭代影响。你也可以说使用常见的控制操作(if,while,for)去实现更复杂的控制流。或者你可以使用提供的影响组合去表达并发 (yield race) 和 平行 (yield [...])。你也可以迭代调用其他Saga,允许强大的常规或者子程序模式。
一般来说,等待一个未知的action,等待像`yield delay(1000)`这样的未知的函数调用结果,或者等待一个调度的结果,这些都是相同的概念。在所有情况下,我们迭代某些形式的Effect。Saga所做的,实际上就是把所有这些Effect组合在一起,去实现期望的控制流。最简单的是一个接着一个的顺序执行yield来迭代Effect。你也可以使用常见的控制操作(if,while,for)去实现更复杂的控制流。或者你可以使用提供的Effect组合去表达并发 (yield race) 和 平行 (yield [...])。你也可以迭代调用其他Saga,允许强大的常规或者子程序模式。
举例来说,`incrementAsync` 使用了无限循环 `while(true)`,它意味着这将会在整个应用程序的生命周期都会存在。
你也可以创建Saga只持续一段时间。举个例子,下面的Saga,等待3个`INCREMENT_COUNTER` actions, 触发一个`showCongratulation()` action,然后结束.
你也可以创建只持续一段时间的Saga。举个例子,下面的Saga,等待3个`INCREMENT_COUNTER` actions, 触发一个`showCongratulation()` action,然后结束.

@@ -147,3 +147,3 @@ ```javascript

Sagas 生成器可以生成多种形式的影响。最简单的方式是生成一个约定。
Sagas 生成器可以生成多种形式的Effect。最简单的方式是生成一个Promise。

@@ -162,3 +162,3 @@ ```javascript

上面的例子,`fetch('/products')` 返回一个约定并且会被Get请求解决。所以这个获取响应会被立刻执行。简单并且顺畅,但是...
上面的例子,`fetch('/products')` 返回一个Promise并且会被Get请求解决。所以这个获取响应会被立刻执行。简单并且顺畅,但是...

@@ -217,3 +217,3 @@ 假设我们想要测试上面的生成器。

`call` 和 `apply`是非常适合函数返回约定结果。还有一个函数 `cps` 可以被使用到处理Node风格的函数(举例: `fn(...args, callback)` where `callback`
`call` 和 `apply`是非常适合函数返回Promise结果。还有一个函数 `cps` 可以被使用到处理Node风格的函数(举例: `fn(...args, callback)` where `callback`
是`(error, result) => ()`的形式)。 举个例子

@@ -238,3 +238,3 @@

你可以在Generator内部使用简单的try/catch语法捕捉异常。在下面的例子中,Saga捕捉 `api.buyProducts` 调用的错误(也就是一个被拒绝的约定)
你可以在Generator内部使用简单的try/catch语法捕捉异常。在下面的例子中,Saga捕捉 `api.buyProducts` 调用的错误(也就是一个被拒绝的Promise)

@@ -280,3 +280,3 @@ ```javascript

`yield`声明是非常棒。它以一个简单并且线形的方式表示异步控制流程。但是我们也需要做一些并行的事情。你不能简单的如下写
`yield`声明非常棒。它以一个简单并且线形的方式表示异步控制流程。但是我们也需要做一些并行的事情。你不能简单的如下写

@@ -289,3 +289,3 @@ ```javascript

因为第二个Effect将不会等到第一个执行结束后再执行,我们必须如下:
因为第二个Effect将等到第一个执行结束后再执行,我们必须改成如下形式:

@@ -304,3 +304,3 @@ ```javascript

有些时候我们开始并行多次任务,但是我们不想等待,我们只需要去得到 *胜利者*:第一个成功运行(或者被拒绝)。`race`函数提供了一种方式去触发多个effect的竞赛。
有些时候我们开始并行多次任务,但是我们不想等待,我们只想得到 *胜利者*:第一个成功运行(或者被拒绝)。`race`函数提供了一种方式去触发多个effect的竞赛。

@@ -357,3 +357,3 @@ 下面的例子展示Saga触发一个远程的获取请求和强迫这个请求1秒过期。

当使用`yield*`提供一个习惯的方式组合Saga。这个方式有一些局限:
当使用`yield*`提供的方式组合Saga时,有一些局限:

@@ -390,3 +390,3 @@ - 你可能想分别测试嵌入的生成器。在测试代码中,这导致一些重复代码这和重复执行的开销是一样的。我们不想执行嵌入的生成器,但是只想确保它被分发正确的参数。

实际上, Sagas比迭代其他effect没有什么不同(未来action, timeouts ...)。这意味着你可以通过所有的其他方式,使用Effect协调器组合这些Saga。
实际上,Sagas相比迭代其他effect没有什么不同(未来action, timeouts ...)。这意味着你可以通过所有的其他方式,使用Effect协调器组合这些Saga。

@@ -429,4 +429,4 @@ 举个例子你也可能想用户必须在规定时间内完成游戏。

`watchFetch` 生成器将会等待到`yield call(fetchApi, '/posts')` 运行结束。想像
`FETCH_POSTS` action 被 `刷新`按钮触发。如果你的应用每次获取禁用这个按钮(不存在并发获取),这里将不会有问题,因为我们自导没有`FETCH_POSTS`action会发生直到我们得到`fetchApi`调用的响应。
`watchFetch` 生成器将会等待到`yield call(fetchApi, '/posts')` 运行结束。设想
`FETCH_POSTS` action 被 `刷新`按钮触发。如果我们的应用每次获取禁用这个按钮(不存在并发获取),这里将不会有问题,因为我们知道没有`FETCH_POSTS`action会发生直到我们得到`fetchApi`调用的响应。

@@ -515,3 +515,3 @@ 但是当应用程序允许用户点击`刷新`按钮而不需要等待当前请求完成,什么事情会发生?

<td>task.done</td>
<td>一个约定
<td>一个Promise
<ul>

@@ -601,3 +601,3 @@ <li>任务完成并返回值 with task's return value</li>

>记住`yield cancel(task)`不会等待取消任务这个操作完成,这一点非常重要。(换句话说去执行它的异常处理是取消这个操作完成的时候)。cancel的作用有点像fork。当cancel开始它就返回值。
>一旦取消,任务需要尽快完成它的清理逻辑。在有些场合,清理逻辑可以包含一些异步操作,取消任务是一个单独的进程,并且这里没有办法重新进入主控制流程(除非通过Redux store调度actiond。然而这会导致复杂的,很难理解的控制流程。 所以最好是尽快结束任务).
>一旦取消,任务需要尽快完成它的清理逻辑。在有些场合,清理逻辑可以包含一些异步操作,取消任务是一个单独的进程,并且这里没有办法重新进入主控制流程(除非通过Redux store调度action。然而这会导致复杂的,很难理解的控制流程。 所以最好是尽快结束任务).

@@ -653,3 +653,3 @@ ##Automatic cancellation

- `dispatch(action) => result`: 用于完成 `put` effect。每次运行`yield put(action)`,`dispatch`会和`action`一起被调用,`dispatch`的返回值被用于完成`put` effect。约定结果自动完成或者取消。
- `dispatch(action) => result`: 用于完成 `put` effect。每次运行`yield put(action)`,`dispatch`会和`action`一起被调用,`dispatch`的返回值被用于完成`put` effect。Promise结果自动完成或者取消。

@@ -656,0 +656,0 @@ - `monitor(sagaAction)` (可选): 是被用于调用所有Saga关联事件的回调。在中间件的版本,所有action都调度到Redux Store。详细查看[sagaMonitor example]

@@ -17,3 +17,3 @@ # redux-saga

> As you'll in the rest of this README. Generators, while they seem lower level than ES7 async
> As you'll see in the rest of this README. Generators, while they seem lower level than ES7 async
functions, allow some features like declarative effects, cancellation. Which are harder, if Not

@@ -55,2 +55,3 @@ impossible, to implement with simple async functions.

#Getting started

@@ -131,3 +132,3 @@

- If PATTERN is a function, the action is matched if PATTERN(action) is true (e.g. `take(action => action.entities)`
will match all actions having a (truthy) `entities`field.
will match all actions having a (truthy) `entities`field.)

@@ -137,3 +138,3 @@ - If PATTERN is a string, the action is matched if action.type === PATTERN (as used above `take(INCREMENT_ASYNC)`

- If PATTERN is an array, action.type is matched against all items in the array (e.g. `take([INCREMENT, DECREMENT])` will
match either actions of type `INCREMENT` or `DECREMENT`.
match either actions of type `INCREMENT` or `DECREMENT`.)

@@ -541,3 +542,3 @@ #Dispatching actions to the store

`fork` accepts function/generator calls as well as simple effects
`fork`, just like `call`, accepts function/generator calls.

@@ -638,3 +639,3 @@ ```javascript

// user clicked stop. cancel the background task
// this will throw a SagaCancellationException into task
// this will throw a SagaCancellationException into the forked bgSync task
yield cancel(bgSyncTask)

@@ -647,5 +648,5 @@ }

inside the currently running task. In the above example, the exception is caught by
`bgSync`. Otherwise, it will propagate up to `main`. And it if `main` doesn't handle it
then it will bubble up the call chain, just as normal JavaScript errors bubble up the
call chain of synchronous functions.
`bgSync`. **Note that uncaught SagaCancellationException are not bubbled upward**. In the
above example, if `bgSync` doesn't catch the cancellation error, the error will not propagate
to `main` (because `main` has already moved on).

@@ -681,3 +682,5 @@ Cancelling a running task will also cancel the current effect where the task is blocked

then another `SagaCancellationException` will be thrown inside `subtask`. If `subtask`
omits to handle the cancellation exception, it will propagate up to `main`.
omits to handle the cancellation exception, a warning message is printed to the console to
warn the developer (the message is only printed if there is a `process.env.NODE_ENV` variable
set and it's set to `'development'`).

@@ -711,5 +714,2 @@ The main purpose of the cancellation exception is to allow cancelled tasks to perform any

Unlike in manual cancellations, unhandled cancellation exceptions are not propagated to the actual
saga running the race/parallel effect. Nevertheless, a warning is logged into the console in case
a cancelled task omitted to handle a cancellation exception.

@@ -774,9 +774,2 @@ #Dynamically starting Sagas with runSaga

Pre-requisites
- browserify
You can also build the examples manually, and open `index.html` at the root of each example
directory to run.
```

@@ -793,8 +786,4 @@ git clone https://github.com/yelouafi/redux-saga.git

```
// run with live-reload server
npm run counter
// manual build
npm run build-counter
// test sample for the generator

@@ -806,8 +795,4 @@ npm run test-counter

```
// run with live-reload server
npm run shop
// manual build
npm run build-shop
// test sample for the generator

@@ -819,8 +804,4 @@ npm run test-shop

```
// run with live-reload server
npm run async
// manual build
npm run build-async
//sorry, no tests yet

@@ -827,0 +808,0 @@ ```

@@ -5,3 +5,3 @@ import middleware from './middleware'

export {
SagaCancellationException,
CANCEL,
RACE_AUTO_CANCEL,

@@ -12,2 +12,6 @@ PARALLEL_AUTO_CANCEL,

import _SagaCancellationException from './SagaCancellationException'
export const SagaCancellationException = _SagaCancellationException
export { is } from './utils'

@@ -14,0 +18,0 @@ export { take, put, race, call, apply, cps, fork, join, cancel, as } from './io'

@@ -1,8 +0,11 @@

import { asap } from './utils'
import { asap, isDev } from './utils'
import proc from './proc'
import emitter from './emitter'
import { MONITOR_ACTION } from './monitorActions'
export default (...sagas) => ({getState, dispatch}) => {
const sagaEmitter = emitter()
const monitor = isDev ? action => asap(() => dispatch(action)) : undefined

@@ -14,3 +17,3 @@ sagas.forEach( saga => {

dispatch,
action => asap(() => dispatch(action)),
monitor,
0,

@@ -23,3 +26,6 @@ saga.name

const result = next(action) // hit reducers
sagaEmitter.emit(action)
// filter out monitor actions to avoid endless loop
// see https://github.com/yelouafi/redux-saga/issues/61
if(!action[MONITOR_ACTION])
sagaEmitter.emit(action)
return result;

@@ -29,2 +35,3 @@ }

}

@@ -1,2 +0,2 @@

export const MONITOR_ACTION = 'MONITOR_ACTION'
export const EFFECT_TRIGGERED = 'EFFECT_TRIGGERED'

@@ -8,2 +8,3 @@ export const EFFECT_RESOLVED = 'EFFECT_RESOLVED'

return {
[MONITOR_ACTION]: true,
type: EFFECT_TRIGGERED,

@@ -16,2 +17,3 @@ effectId, parentEffectId, label, effect

return {
[MONITOR_ACTION]: true,
type: EFFECT_RESOLVED,

@@ -24,2 +26,3 @@ effectId, result

return {
[MONITOR_ACTION]: true,
type: EFFECT_REJECTED,

@@ -26,0 +29,0 @@ effectId, error

@@ -1,7 +0,9 @@

import { noop, is, check, remove, deferred, autoInc, asap, TASK } from './utils'
import { noop, is, isDev, check, remove, deferred, autoInc, asap, TASK } from './utils'
import { as, matcher } from './io'
import * as monitorActions from './monitorActions'
import SagaCancellationException from './SagaCancellationException'
export const NOT_ITERATOR_ERROR = 'proc first argument (Saga function result) must be an iterator'
export const CANCEL = Symbol('@@redux-saga/cancelPromise')
export const PARALLEL_AUTO_CANCEL = 'PARALLEL_AUTO_CANCEL'

@@ -13,12 +15,2 @@ export const RACE_AUTO_CANCEL = 'RACE_AUTO_CANCEL'

export const CANCEL = Symbol('@@redux-saga/cancelPromise')
export class SagaCancellationException {
constructor(type, saga, origin) {
this.type = type
this.saga = saga
this.origin = origin
}
}
export default function proc(

@@ -35,31 +27,76 @@ iterator,

const deferredInputs = []
// tracks the current `take` effects
let deferredInputs = []
const canThrow = is.throw(iterator)
// Promise to be resolved/rejected when this generator terminates (or throws)
const deferredEnd = deferred()
// subscribe to input events, this will resolve the current `take` effects
const unsubscribe = subscribe(input => {
deferredInputs.forEach( def => {
if(def.match(input))
def.resolve(input)
})
})
for (let i = 0; i < deferredInputs.length; i++) {
const def = deferredInputs[i]
if(def.match(input)) {
// cancel all deferredInputs; parallel takes are disallowed
// and in concurrent takes, first wins
deferredInputs = []
def.resolve(input)
}
}
})
iterator._isRunning = true
next()
/**
cancel : (SagaCancellationException) -> ()
return newTask(
Tracks the current effect cancellation
Each time the generator progresses. calling runEffect will set a new value
on it. It allows propagating cancellation to child effects
**/
next.cancel = noop
/**
Creates a new task descriptor for this generator
**/
const task = newTask(
parentEffectId, name, iterator, deferredEnd.promise
)
function next(arg, isError) {
/**
this maybe called by a parent generator to trigger/propagate cancellation
W'll simply cancel the current effect, which will reject that effect
The rejection will throw the injected SagaCancellationException into the flow
of this generator
**/
task.done[CANCEL] = ({type, origin}) => {
next.cancel(
new SagaCancellationException(type, name, origin)
)
}
// tracks the running status
iterator._isRunning = true
// kicks up the generator
next()
// then return the task descriptor to the caller
return task
/**
This is the generator driver
It's a recursive aysnc/continuation function which calls itself
until the generator terminates or throws
**/
function next(error, arg) {
// Preventive measure. If we endup here, then there is really something wrong
if(!iterator._isRunning)
return
throw new Error('Trying to resume an already finished generator')
try {
if(isError && !canThrow)
throw arg
const result = isError ? iterator.throw(arg) : iterator.next(arg)
if(error && !canThrow)
throw error
// calling iterator.throw on a generator that doesnt defined a correponding try/Catch
const result = error ? iterator.throw(error) : iterator.next(arg)
if(!result.done) {
const currentEffect = runEffect(result.value, parentEffectId)
deferredEnd.promise[CANCEL] = currentEffect[CANCEL]
currentEffect.then(next, err => next(err, true))
runEffect(result.value, parentEffectId, '', next)
} else {

@@ -70,3 +107,5 @@ end(result.value)

/*eslint-disable no-console*/
console.warn(`${name}: uncaught`, error )
if(isDev) {
console.warn(`${name}: uncaught`, error )
}
end(error, true)

@@ -88,78 +127,143 @@ }

function runEffect(effect, parentEffectId, label = '') {
function runEffect(effect, parentEffectId, label = '', cb) {
const effectId = nextEffectId()
monitor( monitorActions.effectTriggered(effectId, parentEffectId, label, effect) )
let data
const promise = (
is.array(effect) ? runParallelEffect(effect, effectId)
: is.iterator(effect) ? proc(effect, subscribe, dispatch, monitor, effectId).done
/**
completion callback and cancel callback are mutually exclusive
We can't cancel an already completed effect
And We can't complete an already cancelled effectId
**/
let effectSettled
: (data = as.take(effect)) ? runTakeEffect(data)
: (data = as.put(effect)) ? runPutEffect(data)
: (data = as.race(effect)) ? runRaceEffect(data, effectId)
: (data = as.call(effect)) ? runCallEffect(data, effectId)
: (data = as.cps(effect)) ? runCPSEffect(data)
: (data = as.fork(effect)) ? runForkEffect(data, effectId)
: (data = as.join(effect)) ? runJoinEffect(data)
: (data = as.cancel(effect)) ? runCancelEffect(data)
// Completion callback passed to the appropriate effect runner
function currCb(err, res) {
if(effectSettled)
return
: /* resolve anything else */ Promise.resolve(effect)
)
effectSettled = true
cb.cancel = noop // defensive measure
err ?
monitor( monitorActions.effectRejected(effectId, err) )
: monitor( monitorActions.effectResolved(effectId, res) )
const def = deferred()
let isRunning = true
const completeWith = fn => outcome => {
if(isRunning) {
isRunning = false
fn(outcome)
}
cb(err, res)
}
promise.then(completeWith(def.resolve), completeWith(def.reject))
def.promise[CANCEL] = ({type, origin}) => {
if(isRunning) {
isRunning = false
const error = new SagaCancellationException(type, name, origin)
cancelPromise(promise, error)
def.reject(error)
}
// tracks down the current cancel
currCb.cancel = noop
// setup cancellation logic on the parent cb
cb.cancel = (cancelError) => {
// prevents cancelling an already completed effect
if(effectSettled)
return
effectSettled = true
/**
propagates cancel downward
catch uncaught cancellations errors,
because w'll throw our own cancellation error inside this generator
**/
try { currCb.cancel(cancelError) } catch(err) { void(0); }
currCb.cancel = noop // defensive measure
/**
triggers/propagates the cancellation error
**/
cb(cancelError)
monitor( monitorActions.effectRejected(effectId, cancelError) )
}
def.promise.then(
result => monitor( monitorActions.effectResolved(effectId, result) ),
error => monitor( monitorActions.effectRejected(effectId, error) )
/**
each effect runner must attach its own logic of cancellation to the provided callback
it allows this generator to propagate cancellation downward.
ATTENTION! effect runners must setup the cancel logic by setting cb.cancel = [cancelMethod]
And the setup must occur before calling the callback
This is a sort of inversion of control: called async functions are responsible
of completing the flow by calling the provided continuation; while caller functions
are responsible for aborting the current flow by calling the attached cancel function
Library users can attach their own cancellation logic to promises by defining a
promise[CANCEL] method in their returned promises
ATTENTION! calling cancel must have no effect on an already completed or cancelled effect
**/
let data
return (
// Non declarative effect
is.promise(effect) ? resolvePromise(effect, currCb)
: is.iterator(effect) ? resolveIterator(effect, effectId, name, currCb)
// declarative effects
: is.array(effect) ? runParallelEffect(effect, effectId, currCb)
: (is.notUndef(data = as.take(effect))) ? runTakeEffect(data, currCb)
: (is.notUndef(data = as.put(effect))) ? runPutEffect(data, currCb)
: (is.notUndef(data = as.race(effect))) ? runRaceEffect(data, effectId, currCb)
: (is.notUndef(data = as.call(effect))) ? runCallEffect(data, effectId, currCb)
: (is.notUndef(data = as.cps(effect))) ? runCPSEffect(data, currCb)
: (is.notUndef(data = as.fork(effect))) ? runForkEffect(data, effectId, currCb)
: (is.notUndef(data = as.join(effect))) ? runJoinEffect(data, currCb)
: (is.notUndef(data = as.cancel(effect))) ? runCancelEffect(data, currCb)
: /* anything else returned as is */ currCb(null, effect)
)
return def.promise
}
function runTakeEffect(pattern) {
const def = deferred({ match : matcher(pattern), pattern })
function resolvePromise(promise, cb) {
const cancelPromise = promise[CANCEL]
if(typeof cancelPromise === 'function') {
cb.cancel = cancelPromise
}
promise.then(
result => cb(null, result),
error => cb(error)
)
}
function resolveIterator(iterator, effectId, name, cb) {
resolvePromise(
proc(iterator, subscribe, dispatch, monitor, effectId, name).done,
cb
)
}
function runTakeEffect(pattern, cb) {
const def = {
match : matcher(pattern),
pattern,
resolve: input => cb(null, input)
}
deferredInputs.push(def)
const done = () => remove(deferredInputs, def)
def.promise.then(done, done)
def.promise[CANCEL] = done
return def.promise
// cancellation logic for take effect
cb.cancel = () => remove(deferredInputs, def)
}
function runPutEffect(action) {
return asap(() => dispatch(action) )
function runPutEffect(action, cb) {
// TODO check why synchronously nested dispatches aren't forwarded to the store
// For now, this workaround allows the dispatch to occur on the next microtask
// But could have side effect on a sync interleaved take/dispatch flow (ARGGHHHHHHH)
asap(() => cb(null, dispatch(action)))
// Put effects are non cancellables
}
function runCallEffect({context, fn, args}, effectId) {
function runCallEffect({context, fn, args}, effectId, cb) {
const result = fn.apply(context, args)
return !is.iterator(result)
? Promise.resolve(result)
: proc(result, subscribe, dispatch, monitor, effectId, fn.name).done
return (
is.promise(result) ? resolvePromise(result, cb)
: is.iterator(result) ? resolveIterator(result, effectId, fn.name, cb)
: cb(null, result)
)
}
function runCPSEffect({context, fn, args}) {
return new Promise((resolve, reject) => {
fn.apply(context, args.concat(
(err, res) => is.undef(err) ? resolve(res) : reject(err)
))
})
function runCPSEffect({context, fn, args}, cb) {
// CPS (ie node style functions) can define their own cancellation logic
// by setting cancel field on the cb
fn.apply(context, args.concat(cb))
}
function runForkEffect({context, fn, args}, effectId) {
function runForkEffect({context, fn, args}, effectId, cb) {
let result, _iterator

@@ -183,56 +287,117 @@

return Promise.resolve(
cb(
null,
proc(_iterator, subscribe, dispatch, monitor, effectId, fn.name, true)
)
// Fork effects are non cancellables
}
function runJoinEffect(task) {
return task.done
function runJoinEffect(task, cb) {
resolvePromise(task.done, cb)
}
function runCancelEffect(task) {
function runCancelEffect(task, cb) {
// cancel the given task
// uncaught cancellations errors bubbles upward
task.done[CANCEL](
new SagaCancellationException(MANUAL_CANCEL, '', name)
new SagaCancellationException(MANUAL_CANCEL, name, name)
)
return Promise.resolve()
cb()
// cancel effects are non cancellables
}
function runParallelEffect(effects, effectId) {
const promises = effects.map(eff => runEffect(eff, effectId))
const ret = Promise.all(promises)
ret[CANCEL] = error => {
promises.forEach(p => cancelPromise(p, error))
// Reimplementing Promise.all. We're in 2016
function runParallelEffect(effects, effectId, cb) {
let completedCount = 0
let completed
const results = Array(effects.length)
const childCbs = effects.map( (eff, idx) => {
const chCbAtIdx = (err, res) => {
// Either we've been cancelled, or an error aborted the whole effect
if(completed)
return
// one of the effects failed
if(err) {
// cancel all other effects
// This is an AUTO_CANCEL (not triggered by a manual cancel)
// Catch uncaught cancellation errors, because w'll only throw the actual
// rejection error (err) inside this generator
try {
cb.cancel(
new SagaCancellationException(PARALLEL_AUTO_CANCEL, name, name)
)
} catch(err) { void(0) }
cb(err)
} else {
results[idx] = res
completedCount++
if(completedCount === results.length) {
completed = true
cb(null, results)
}
}
}
chCbAtIdx.cancel = noop
return chCbAtIdx
})
// This is different, a cancellation coming from upward
// either a MANUAL_CANCEL or a parent AUTO_CANCEL
// No need to catch, will be swallowed by the caller
cb.cancel = cancelError => {
// prevents unnecessary cancellation
if(!completed) {
completed = true
childCbs.forEach(chCb => chCb.cancel(cancelError))
}
}
ret.catch(() => {
ret[CANCEL](
new SagaCancellationException(PARALLEL_AUTO_CANCEL, name, name)
)
})
return ret
effects.forEach( (eff, idx) => runEffect(eff, effectId, idx, childCbs[idx]) )
}
function runRaceEffect(effects, effectId) {
const promises = []
const retP = Promise.race(
Object.keys(effects)
.map(key => {
const promise = runEffect(effects[key], effectId, key)
promises.push(promise)
return promise.then(
result => ({[key]: result}),
error => Promise.reject({[key]: error})
)
})
)
// And yet; Promise.race
function runRaceEffect(effects, effectId, cb) {
let completed
const keys = Object.keys(effects)
const childCbs = {}
retP[CANCEL] = error => {
promises.forEach(p => cancelPromise(p, error))
keys.forEach(key => {
const chCbAtKey = (err, res) => {
// Either we've been cancelled, or an error aborted the whole effect
if(completed)
return
if(err) {
// Race Auto cancellation
try {
cb.cancel(
new SagaCancellationException(RACE_AUTO_CANCEL, name, name)
)
} catch(err) { void(0) }
cb({[key]: err})
} else {
try {
cb.cancel(
new SagaCancellationException(RACE_AUTO_CANCEL, name, name)
)
} catch(err) { void(0) }
completed = true
cb(null, {[key]: res})
}
}
chCbAtKey.cancel = noop
childCbs[key] = chCbAtKey
})
cb.cancel = cancelError => {
// prevents unnecessary cancellation
if(!completed) {
completed = true
keys.forEach(key => childCbs[key].cancel(cancelError))
}
}
const done = () => retP[CANCEL](
new SagaCancellationException(RACE_AUTO_CANCEL, name, name)
)
retP.then(done, done)
return retP
keys.forEach(key => runEffect(effects[key], effectId, key, childCbs[key]))
}

@@ -253,6 +418,2 @@

function cancelPromise(promise, error) {
if(promise[CANCEL])
promise[CANCEL](error)
}
}

@@ -5,2 +5,4 @@ export const TASK = Symbol('TASK')

export const isDev = typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'development'
export function check(value, predicate, error) {

@@ -7,0 +9,0 @@ if(! predicate(value) )

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc