react-hook-use-async
Version:
Playing with an async task in React
180 lines (153 loc) • 5.62 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Task = Task;
exports["default"] = void 0;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = require("react");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var noop = function noop() {};
var ABORT_ERROR = {};
function Task(promise) {
var cancel = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop;
this.promise = promise instanceof Promise ? promise : Promise.resolve(promise);
this.cancel = cancel;
}
function executeTask(createTask, inputs) {
var cleanups = [];
var cancel = function cancel() {
cleanups.forEach(function (cleanup) {
return cleanup();
});
};
var isCanceled = false;
cleanups.push(function () {
isCanceled = true;
});
var promise = new Promise(function (resolve, reject) {
try {
var task = createTask(inputs);
if (!(task instanceof Task)) {
task = new Task(task);
}
task.promise.then(function (result) {
return !isCanceled && resolve(result);
}, function (error) {
return !isCanceled && reject(error);
});
cleanups.push(function () {
return task.cancel();
});
cleanups.push(function () {
return reject(ABORT_ERROR);
});
} catch (error) {
reject(error);
}
});
return {
cancel: cancel,
promise: promise
};
}
function useAsync(createTask) {
var inputs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
onError = _ref.onError,
onCancel = _ref.onCancel,
onSuccess = _ref.onSuccess,
_ref$isOnDemand = _ref.isOnDemand,
isOnDemand = _ref$isOnDemand === void 0 ? false : _ref$isOnDemand;
var staticConfig = (0, _react.useRef)({
isOnDemand: isOnDemand
}).current;
var selfRef = (0, _react.useRef)({
task: {
cancel: noop
}
});
var self = selfRef.current;
(0, _react.useEffect)(function () {
Object.assign(self, {
onError: onError,
onCancel: onCancel,
onSuccess: onSuccess,
createTask: createTask
});
});
var _useState = (0, _react.useState)(0),
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
count = _useState2[0],
setCount = _useState2[1];
var execute = function execute() {
setCount(function (prevCount) {
return prevCount + 1;
});
};
var _useState3 = (0, _react.useState)({
isPending: false
}),
_useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
state = _useState4[0],
setState = _useState4[1];
(0, _react.useEffect)(function () {
if (staticConfig.isOnDemand && count === 0) {
return noop;
}
var createTaskSelf = self.createTask,
_self$onError = self.onError,
onErrorSelf = _self$onError === void 0 ? noop : _self$onError,
_self$onCancel = self.onCancel,
onCancelSelf = _self$onCancel === void 0 ? noop : _self$onCancel,
_self$onSuccess = self.onSuccess,
onSuccessSelf = _self$onSuccess === void 0 ? noop : _self$onSuccess;
var task = executeTask(createTaskSelf, inputs);
setState(function (prevState) {
return _objectSpread({}, prevState, {
isPending: true
});
});
var setStateCurrentTask = function setStateCurrentTask(args) {
if (self.task === task) {
setState(args);
}
};
task.promise.then(function (result) {
setStateCurrentTask({
result: result,
isPending: false
});
onSuccessSelf(result, inputs);
}, function (error) {
if (error === ABORT_ERROR) {
setStateCurrentTask(function (prevState) {
return _objectSpread({}, prevState, {
isPending: false
});
});
onCancelSelf(inputs);
} else {
setStateCurrentTask({
error: error,
isPending: false
});
onErrorSelf(error, inputs);
}
});
self.task = task;
return function () {
task.cancel();
};
}, // eslint-disable-next-line react-hooks/exhaustive-deps
[count].concat((0, _toConsumableArray2["default"])(staticConfig.isOnDemand ? [] : inputs)));
return _objectSpread({
execute: execute
}, state, {}, self.task);
}
var _default = useAsync;
exports["default"] = _default;