Skip to content

Commit

Permalink
Fix regression with preserving this context (#16)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
  • Loading branch information
darcyparker and sindresorhus authored Jan 22, 2021
1 parent a9ad96b commit cfed83c
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 4 deletions.
8 changes: 4 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const pDebounce = (fn, wait, options = {}) => {
timer = setTimeout(() => {
timer = null;

const result = options.leading ? leadingValue : fn(...arguments_);
const result = options.leading ? leadingValue : fn.apply(this, arguments_);

for (resolve of resolveList) {
resolve(result);
Expand All @@ -28,7 +28,7 @@ const pDebounce = (fn, wait, options = {}) => {
}, wait);

if (runImmediately) {
leadingValue = fn(...arguments_);
leadingValue = fn.apply(this, arguments_);
resolve(leadingValue);
} else {
resolveList.push(resolve);
Expand All @@ -40,13 +40,13 @@ const pDebounce = (fn, wait, options = {}) => {
pDebounce.promise = function_ => {
let currentPromise;

return async (...arguments_) => {
return async function (...arguments_) {
if (currentPromise) {
return currentPromise;
}

try {
currentPromise = function_(...arguments_);
currentPromise = function_.apply(this, arguments_);
return await currentPromise;
} finally {
currentPromise = undefined;
Expand Down
40 changes: 40 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,43 @@ test('leading option - does not call input function after timeout', async t => {

t.is(count, 1);
});

// Factory to create a separate class for each test below
// * Each test replaces methods in the class with a debounced variant,
// hence the need to start with fresh class for each test.
const createFixtureClass = () => class {
constructor() {
this._foo = fixture;
}

foo() {
// If `this` is not preserved by `pDebounce()` or `pDebounce.promise()`,
// then `this` will be undefined and accessing `this._foo` will throw.
return this._foo;
}

getThis() {
// If `this` is not preserved by `pDebounce()` or `pDebounce.promise()`,
// then `this` will be undefined.
return this;
}
};

const preserveThisCases = [
['pDebounce()', pDebounce],
['pDebounce().promise()', pDebounce.promise]
];

for (const [name, debounceFn] of preserveThisCases) {
test(`\`this\` is preserved in ${name} fn`, async t => {
const FixtureClass = createFixtureClass();
FixtureClass.prototype.foo = debounceFn(FixtureClass.prototype.foo, 10);
FixtureClass.prototype.getThis = debounceFn(FixtureClass.prototype.getThis, 10);

const thisFixture = new FixtureClass();

t.is(await thisFixture.getThis(), thisFixture);
await t.notThrowsAsync(thisFixture.foo());
t.is(await thisFixture.foo(), fixture);
});
}

0 comments on commit cfed83c

Please sign in to comment.