diff --git a/package.json b/package.json index 2ce6f8c4b..cca53a8ae 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "fs-extra": "^1.0.0", "fs-promise": "^1.0.0", "get-stream": "^3.0.0", + "golike-defer": "^0.0.0", "hashy": "~0.5.1", "helmet": "^3.0.0", "highland": "^2.5.1", diff --git a/src/decorators.js b/src/decorators.js index 2e0d98d78..de78e4db0 100644 --- a/src/decorators.js +++ b/src/decorators.js @@ -2,10 +2,7 @@ import bind from 'lodash/bind' import { isArray, - isPromise, - isFunction, - noop, - pFinally + isFunction } from './utils' // =================================================================== @@ -98,117 +95,6 @@ export const debounce = duration => (target, name, descriptor) => { // ------------------------------------------------------------------- -const _push = Array.prototype.push - -export const deferrable = (target, name, descriptor) => { - let fn - function newFn () { - const deferreds = [] - const defer = fn => { - deferreds.push(fn) - } - defer.clear = () => { - deferreds.length = 0 - } - - const args = [ defer ] - _push.apply(args, arguments) - - let executeDeferreds = () => { - let i = deferreds.length - while (i) { - deferreds[--i]() - } - } - - try { - const result = fn.apply(this, args) - - if (isPromise(result)) { - result::pFinally(executeDeferreds) - - // Do not execute the deferreds in the finally block. - executeDeferreds = noop - } - - return result - } finally { - executeDeferreds() - } - } - - if (descriptor) { - fn = descriptor.value - descriptor.value = newFn - - return descriptor - } - - fn = target - return newFn -} - -// Deferred functions are only executed on failures. -// -// i.e.: defer.clear() is automatically called in case of success. -deferrable.onFailure = (target, name, descriptor) => { - let fn - function newFn (defer) { - const result = fn.apply(this, arguments) - - return isPromise(result) - ? result.then(result => { - defer.clear() - return result - }) - : (defer.clear(), result) - } - - if (descriptor) { - fn = descriptor.value - descriptor.value = newFn - } else { - fn = target - target = newFn - } - - return deferrable(target, name, descriptor) -} - -// Deferred functions are only executed on success. -// -// i.e.: defer.clear() is automatically called in case of failure. -deferrable.onSuccess = (target, name, descriptor) => { - let fn - function newFn (defer) { - try { - const result = fn.apply(this, arguments) - - return isPromise(result) - ? result.then(null, error => { - defer.clear() - throw error - }) - : result - } catch (error) { - defer.clear() - throw error - } - } - - if (descriptor) { - fn = descriptor.value - descriptor.value = newFn - } else { - fn = target - target = newFn - } - - return deferrable(target, name, descriptor) -} - -// ------------------------------------------------------------------- - const _ownKeys = ( typeof Reflect !== 'undefined' && Reflect.ownKeys || (({ diff --git a/src/decorators.spec.js b/src/decorators.spec.js index 0a5e84177..96318e74f 100644 --- a/src/decorators.spec.js +++ b/src/decorators.spec.js @@ -4,7 +4,7 @@ import expect from 'must' // =================================================================== -import {autobind, debounce, deferrable} from './decorators' +import {autobind, debounce} from './decorators' // =================================================================== @@ -76,98 +76,3 @@ describe('debounce()', () => { }, 2e1) }) }) - -// ------------------------------------------------------------------- - -describe('deferrable()', () => { - it('works with normal termination', () => { - let i = 0 - const fn = deferrable(defer => { - i += 2 - defer(() => { i -= 2 }) - - i *= 2 - defer(() => { i /= 2 }) - - return i - }) - - expect(fn()).to.equal(4) - expect(i).to.equal(0) - }) - - it('defer.clear() removes previous deferreds', () => { - let i = 0 - const fn = deferrable(defer => { - i += 2 - defer(() => { i -= 2 }) - - defer.clear() - - i *= 2 - defer(() => { i /= 2 }) - - return i - }) - - expect(fn()).to.equal(4) - expect(i).to.equal(2) - }) - - it('works with exception', () => { - let i = 0 - const fn = deferrable(defer => { - i += 2 - defer(() => { i -= 2 }) - - i *= 2 - defer(() => { i /= 2 }) - - throw i - }) - - expect(() => fn()).to.throw(4) - expect(i).to.equal(0) - }) - - it('works with promise resolution', async () => { - let i = 0 - const fn = deferrable(async defer => { - i += 2 - defer(() => { i -= 2 }) - - i *= 2 - defer(() => { i /= 2 }) - - // Wait a turn of the events loop. - await Promise.resolve() - - return i - }) - - await expect(fn()).to.eventually.equal(4) - expect(i).to.equal(0) - }) - - it('works with promise rejection', async () => { - let i = 0 - const fn = deferrable(async defer => { - // Wait a turn of the events loop. - await Promise.resolve() - - i += 2 - defer(() => { i -= 2 }) - - i *= 2 - defer(() => { i /= 2 }) - - // Wait a turn of the events loop. - await Promise.resolve() - - throw i - }) - - await expect(fn()).to.reject.to.equal(4) - expect(i).to.equal(0) - }) -}) diff --git a/src/xapi/index.js b/src/xapi/index.js index 5c78af0b1..6a5b9dcde 100644 --- a/src/xapi/index.js +++ b/src/xapi/index.js @@ -1,5 +1,6 @@ /* eslint-disable camelcase */ +import deferrable from 'golike-defer' import every from 'lodash/every' import fatfs from 'fatfs' import find from 'lodash/find' @@ -20,10 +21,7 @@ import { import httpRequest from '../http-request' import fatfsBuffer, { init as fatfsBufferInit } from '../fatfs-buffer' -import { - deferrable, - mixin -} from '../decorators' +import { mixin } from '../decorators' import { bufferToStream, camelToSnakeCase, diff --git a/src/xapi/mixins/vm.js b/src/xapi/mixins/vm.js index 9479e2c53..73d085d9a 100644 --- a/src/xapi/mixins/vm.js +++ b/src/xapi/mixins/vm.js @@ -1,10 +1,8 @@ +import deferrable from 'golike-defer' import find from 'lodash/find' import gte from 'lodash/gte' import lte from 'lodash/lte' -import { - deferrable -} from '../../decorators' import { forEach, mapToArray, diff --git a/src/xo-mixins/backups.js b/src/xo-mixins/backups.js index f52e38aba..dd4bfac15 100644 --- a/src/xo-mixins/backups.js +++ b/src/xo-mixins/backups.js @@ -1,3 +1,4 @@ +import deferrable from 'golike-defer' import endsWith from 'lodash/endsWith' import escapeStringRegexp from 'escape-string-regexp' import eventToPromise from 'event-to-promise' @@ -15,9 +16,6 @@ import { utcFormat } from 'd3-time-format' import vhdMerge, { chainVhd } from '../vhd-merge' import xapiObjectToXo from '../xapi-object-to-xo' -import { - deferrable -} from '../decorators' import { forEach, mapToArray,