2013-05-16 13 views
8

Czytałem o schemacie Obietnica i próbowałem zakodować wersję w PHP za pomocą kilku przykładów i mojego własnego zrozumienia, jak to powinno działać. Czy wymyśliłem rozsądny przykład wzoru Obietnicy, czy też wprowadziłem go niewłaściwie?Czy ta implementacja jest uczciwym przykładem obietnicy w PHP?

class PromiseClass { 
    private $callbacks = array(); 
    private $last_return; 
    function promise($promise) { 
     if (get_class($promise) == 'Promise') { 
      return $promise; 
     } else if (is_callable($promise)) { 
      $this->then($promise); 
      return $this; 
     } 
    } 
    public function then (callable $callback) { 
     $this->callbacks[] = $callback; 
     return $this; 
    } 
    public function resolve() { 
     $callback = array_shift($this->callbacks); 
     if (is_callable($callback)) { 
      $this->last_return = $callback($this->last_return); 
     } 
     if (count($this->callbacks) > 0) { 
      $this->resolve(); 
     } 
    } 
} 

Przykład użycia:

$promiser->promise(function() { 
     echo "sleeping\n"; 
     sleep(3); 
     return 3; 
    }) 
    ->then(function($args) { 
     echo " in second function, $args\n"; 
    }); 
$promiser->resolve(); 
+3

To lepiej nadaje się do codereview.stackexchange.com –

+0

@JohnConde ma rację. Jednak, aby zmniejszyć swoją ciekawość - jest to rzeczywiście wzór Obietnica w PHP! ... Tyle tylko, że 'sleep()' jest blokowane. Odpowiedź przychodząca. –

Odpowiedz

12

Implementacja obietnica jest głównie poprawne. Istnieje jednak pewien problem: przynajmniej w PHP jest on w zasadzie bezużyteczny i prawie całkowicie równoważny z wzorcem Observer'a wikipediamsdnoodesign.

PHP jest prawie całkowicie jednowątkowe. sleep nie jest wyjątkiem. W związku z tym cała Twoja obietnica zablokuje twój skrypt, dopóki nie zostanie ukończony. W rezultacie widząc, jak operacje są wykonywane inline, możesz równie dobrze nie zawracać sobie głowy.

Możliwym sposobem na pozbycie się tego małego problemu byłoby spowodowanie, że Twoja obietnica rozwidla się z głównego skryptu, co jest możliwe przy użyciu rodziny funkcji PCNTL. Umożliwi to uruchomienie kodu obietnicy w tle, podczas gdy główny skrypt będzie kontynuowany. Kiedy obietnica się zakończy, wraca.

Sposób wykonania tej czynności przedstawiono pod numerem http://www.php.net/manual/en/function.pcntl-fork.php#98711. Aktywnie korzysta z pcntl_fork, co pozwala na rozwidlenie nowego wątku. Ma wady - największa z nich to niezdolność do przekazania głównego procesu przez cokolwiek innego niż sygnały.

+4

Piekło wywołania zwrotnego występuje również w synchronizacji, jeśli chcesz wykonywać [wielozadaniowość kooperacyjną] (http://en.wikipedia.org/wiki/Computer_multitasking#Cooperative_multitasking). Btw, jeśli masz php 5.5, lepiej używać [generatorów] (http://www.php.net/manual/en/language.generators.php) (od 20 czerwca 2013) zamiast obietnic ... Ohh i ofc możesz mieć wątki w php z rozszerzeniem [pthreads] (http://pthreads.org/) (od 2012) ... Tak więc ta odpowiedź jest "najczęściej bezużyteczna" ... – inf3rno

+0

Szukałem tej informacji na https://github.com/reactphp/promise. Nic nie mówi o zakończeniu skryptu. Powinni dodać link do tego posta na swojej stronie –

+0

pcntl obsługuje teraz również informacje kontekstowe: https://wiki.php.net/rfc/additional-context-in-pcntl-signal-handler –

Powiązane problemy