@@ -583,15 +583,20 @@ public function testNoCatchMethodBubblesThrowables() {
583
583
public function testWait () {
584
584
$ callCount = 0 ;
585
585
$ resolveCallback = null ;
586
- $ executor = function (callable $ resolve , callable $ reject ) use (&$ resolveCallback ):void {
586
+ $ rejectCallback = null ;
587
+ $ completeCallback = null ;
588
+ $ executor = function (callable $ resolve , callable $ reject , callable $ complete ) use (&$ resolveCallback , &$ rejectCallback , &$ completeCallback ):void {
587
589
$ resolveCallback = $ resolve ;
590
+ $ rejectCallback = $ reject ;
591
+ $ completeCallback = $ complete ;
588
592
};
589
593
$ resolvedValue = "Done! " ;
590
594
$ sut = new Promise ($ executor );
591
595
592
- $ waitTask = function () use (&$ callCount , $ resolveCallback , $ resolvedValue ) {
596
+ $ waitTask = function () use (&$ callCount , $ resolveCallback , $ resolvedValue, $ completeCallback ) {
593
597
if ($ callCount >= 10 ) {
594
598
call_user_func ($ resolveCallback , $ resolvedValue );
599
+ call_user_func ($ completeCallback );
595
600
}
596
601
else {
597
602
$ callCount ++;
@@ -606,15 +611,20 @@ public function testWait() {
606
611
public function testWaitNotUnwrapped () {
607
612
$ callCount = 0 ;
608
613
$ resolveCallback = null ;
609
- $ executor = function (callable $ resolve , callable $ reject ) use (&$ resolveCallback ):void {
614
+ $ rejectCallback = null ;
615
+ $ completeCallback = null ;
616
+ $ executor = function (callable $ resolve , callable $ reject , callable $ complete ) use (&$ resolveCallback , &$ rejectCallback , &$ completeCallback ):void {
610
617
$ resolveCallback = $ resolve ;
618
+ $ rejectCallback = $ reject ;
619
+ $ completeCallback = $ complete ;
611
620
};
612
621
$ resolvedValue = "Done! " ;
613
622
$ sut = new Promise ($ executor );
614
623
615
- $ waitTask = function () use (&$ callCount , $ resolveCallback , $ resolvedValue ) {
624
+ $ waitTask = function () use (&$ callCount , $ resolveCallback , $ resolvedValue, $ completeCallback ) {
616
625
if ($ callCount >= 10 ) {
617
626
call_user_func ($ resolveCallback , $ resolvedValue );
627
+ call_user_func ($ completeCallback );
618
628
}
619
629
else {
620
630
$ callCount ++;
@@ -629,18 +639,23 @@ public function testWaitNotUnwrapped() {
629
639
public function testWaitUnwrapsFinalValue () {
630
640
$ callCount = 0 ;
631
641
$ resolveCallback = null ;
632
- $ executor = function (callable $ resolve , callable $ reject ) use (&$ resolveCallback ):void {
642
+ $ rejectCallback = null ;
643
+ $ completeCallback = null ;
644
+ $ executor = function (callable $ resolve , callable $ reject , callable $ complete ) use (&$ resolveCallback , &$ rejectCallback , &$ completeCallback ):void {
633
645
$ resolveCallback = $ resolve ;
646
+ $ rejectCallback = $ reject ;
647
+ $ completeCallback = $ complete ;
634
648
};
635
649
$ resolvedValue = "Done! " ;
636
650
$ sut = new Promise ($ executor );
637
651
$ sut ->then (function ($ fulfilled ) {
638
652
return "Returned from within onFulfilled! " ;
639
653
});
640
654
641
- $ waitTask = function () use (&$ callCount , $ resolveCallback , $ resolvedValue ) {
655
+ $ waitTask = function () use (&$ callCount , $ resolveCallback , $ resolvedValue, $ completeCallback ) {
642
656
if ($ callCount >= 10 ) {
643
657
call_user_func ($ resolveCallback , $ resolvedValue );
658
+ call_user_func ($ completeCallback );
644
659
}
645
660
else {
646
661
$ callCount ++;
@@ -680,12 +695,80 @@ public function testFulfilledReturnsNewPromiseThatIsResolved() {
680
695
return $ messagePromise ;
681
696
})->then (self ::mockCallable (1 , "Your number is 105 " ));
682
697
683
- // TODO: Issue #12: 105 resolves before the message does, so the numberPromise's then function will return a pending Promise.
684
- // The chained then should only be called after the message is resolved, so this needs to be stored internally somewhere for fulfillment.
685
698
$ numberPromiseContainer ->resolve (105 );
686
699
$ messagePromiseContainer ->resolve ("Your number is $ numberToResolveWith " );
687
700
}
688
701
702
+ /**
703
+ * Similar test to the one above, but done in a different style.
704
+ * Closer to a real-world usage, this emulates getting a person's
705
+ * address from their name, from an external list.
706
+ */
707
+ public function testFulfilledReturnsNewPromiseThatIsResolved2 () {
708
+ // Our fake data source that will be "searched" by a deferred task (not using an
709
+ // actual Deferred object, but instead, longhand performing a loop outside
710
+ // of the Promise callback).
711
+ $ addressBook = [
712
+ "Adrian Appleby " => "16B Acorn Grove " ,
713
+ "Bentley Buttersworth " => "59 Brambetwicket Drive " ,
714
+ "Cacey Coggleton " => "10 Cambridge Road " ,
715
+ ];
716
+ // The search term used to resolve the first promise with.
717
+ $ searchTerm = null ;
718
+ // We will store any parameters received by the promise fulfilment callbacks.
719
+ $ receivedNames = [];
720
+ $ receivedAddresses = [];
721
+
722
+ // All references to the various callbacks, usually handled by a Deferred:
723
+ $ fulfill = null ;
724
+ $ reject = null ;
725
+ $ complete = null ;
726
+ $ innerFulfill = null ;
727
+ $ innerReject = null ;
728
+ $ innerComplete = null ;
729
+ $ innerPromise = null ;
730
+
731
+ $ sut = new Promise (function ($ f , $ r , $ c ) use (&$ fulfill , &$ reject , &$ complete ) {
732
+ $ fulfill = $ f ;
733
+ $ reject = $ r ;
734
+ $ complete = $ c ;
735
+ });
736
+
737
+ // Define asynchronous behaviour:
738
+ $ sut ->then (function (string $ name ) use (&$ innerFulfil , &$ innerReject , &$ innerComplete , &$ innerPromise , &$ searchTerm , &$ receivedNames ) {
739
+ array_push ($ receivedNames , $ name );
740
+ $ searchTerm = $ name ;
741
+
742
+ $ innerPromise = new Promise (function ($ f , $ r , $ c ) use (&$ innerFulfil , &$ innerReject , &$ innerComplete ) {
743
+ $ innerFulfil = $ f ;
744
+ $ innerReject = $ r ;
745
+ $ innerComplete = $ c ;
746
+ });
747
+ return $ innerPromise ;
748
+ })->then (function (string $ address ) use (&$ receivedAddresses ) {
749
+ array_push ($ receivedAddresses , $ address );
750
+ });
751
+
752
+ // This is the "user code" that initiates the search.
753
+ // Completing the promise resolution with "Butter" will call the Promise's
754
+ // onFulfilled callback, thus our $searchTerm variable should contain "Butter".
755
+ call_user_func ($ fulfill , "Butter " );
756
+ call_user_func ($ complete );
757
+ self ::assertEquals ("Butter " , $ searchTerm );
758
+
759
+ // This is the deferred task for the search:
760
+ foreach ($ addressBook as $ name => $ address ) {
761
+ if (strstr ($ name , $ searchTerm )) {
762
+ call_user_func ($ innerFulfil , $ address );
763
+ call_user_func ($ innerComplete );
764
+ }
765
+ }
766
+
767
+ self ::assertCount (1 , $ receivedNames );
768
+ self ::assertCount (1 , $ receivedAddresses );
769
+ self ::assertEquals ($ addressBook ["Bentley Buttersworth " ], $ receivedAddresses [0 ]);
770
+ }
771
+
689
772
protected function getTestPromiseContainer ():TestPromiseContainer {
690
773
$ resolveCallback = null ;
691
774
$ rejectCallback = null ;
0 commit comments