diff --git a/src/Promise.php b/src/Promise.php index 0ef8ed9e..32912d46 100644 --- a/src/Promise.php +++ b/src/Promise.php @@ -91,7 +91,10 @@ public function cancel() return; } - $this->call($this->canceller); + $canceller = $this->canceller; + $this->canceller = null; + + $this->call($canceller); } private function resolver(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null) diff --git a/tests/PromiseTest/CancelTestTrait.php b/tests/PromiseTest/CancelTestTrait.php index d6c09566..d722d756 100644 --- a/tests/PromiseTest/CancelTestTrait.php +++ b/tests/PromiseTest/CancelTestTrait.php @@ -189,6 +189,31 @@ public function cancelShouldTriggerCancellerWhenAllChildrenCancel() $child2->cancel(); } + /** @test */ + public function cancelShouldNotTriggerCancellerWhenCancellingOneChildrenMultipleTimes() + { + $adapter = $this->getPromiseTestAdapter($this->expectCallableNever()); + + $child1 = $adapter->promise() + ->then() + ->then(); + + $child2 = $adapter->promise() + ->then(); + + $child1->cancel(); + $child1->cancel(); + } + + /** @test */ + public function cancelShouldTriggerCancellerOnlyOnceWhenCancellingMultipleTimes() + { + $adapter = $this->getPromiseTestAdapter($this->expectCallableOnce()); + + $adapter->promise()->cancel(); + $adapter->promise()->cancel(); + } + /** @test */ public function cancelShouldAlwaysTriggerCancellerWhenCalledOnRootPromise() {