考虑一下:
val f1 = Future {}
val f2 = Future {}
f1.flatMap(_ => f2)
在这种情况下,f2
完成之前f1
是否可能完成?
我怀疑是的。
那我怎么能解决这个问题呢?我的意思是,如何才能确保f2
仅在f1
完成后启动?
这会有效/(做好风格):
def f1 = Future {}
def f2 = Future {}
f1.flatMap(_ => f2)
答案 0 :(得分:1)
一旦你定义了一个Future {}
它就会马上启动,这意味着你定义f1和f2为两个期货f1开始执行然后f2正确启动。
所以任何人都可以先完成。
如果您将Future
定义为val
,请立即执行下面的REPL示例。
scala> import scala.concurrent.Future
import scala.concurrent.Future
scala> import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.ExecutionContext.Implicits.global
scala> val f1 = Future { Thread.sleep(5000); println("f1 finished")}
f1: scala.concurrent.Future[Unit] = Future(<not completed>)
scala> val f2 = Future { println("f2 finished")}
f2 finished
f2: scala.concurrent.Future[Unit] = Future(<not completed>)
scala> f1 finished
您可以使用理解来确保首先启动f1,。理解本身扩展到flatMap
scala> for { f1 <- Future { Thread.sleep(5000); println("f1 started"); 100}
| f2 <- Future { println("f2 started"); 200 }
| } yield (f1, f2)
res1: scala.concurrent.Future[(Int, Int)] = Future(<not completed>)
scala> f1 started
f2 started
或者甚至在您的示例中,您可以使用内联期货而非评估变量。
scala> Future { Thread.sleep(5000); println("f1 finished")}.flatMap {f => Future {println("f2 started"); 200}}
res2: scala.concurrent.Future[Int] = Future(<not completed>)
scala> f1 finished
f2 started
最好的方法是使用功能,
scala> def f1 = Future { Thread.sleep(5000); println("f1 finished")}
f1: scala.concurrent.Future[Unit]
scala> def f2 = Future {println("f2 started"); 200}
f2: scala.concurrent.Future[Int]
scala> f1.flatMap(_ => f2)
res3: scala.concurrent.Future[Int] = Future(<not completed>)
scala> f1 finished
f2 started
答案 1 :(得分:0)
用 def 替换 val,基本上是即时计算到惰性计算。
<?php
namespace App\Event\Subscriber;
use App\Entity\BackendUser;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityUpdatedEvent;
class EasyAdminHooksSubscriber implements EventSubscriberInterface {
/**
* @var UserPasswordEncoderInterface
*/
private $passwordEncoder;
/**
* @var ContainerInterface
*/
private $container;
/**
* EasyAdminSubscriber constructor.
*
* @param UserPasswordEncoderInterface $passwordEncoder
* @param ContainerInterface $container
*/
public function __construct(UserPasswordEncoderInterface $passwordEncoder, ContainerInterface $container) {
$this->passwordEncoder = $passwordEncoder;
$this->container = $container;
}
public static function getSubscribedEvents(): array {
return array(
BeforeEntityUpdatedEvent::class => array('preUpdateEntity')
);
}
/**
* @param BeforeEntityUpdatedEvent $event
*
* @noinspection PhpUnused
*/
public function preUpdateEntity(BeforeEntityUpdatedEvent $event) {
$entity = $event->getEntityInstance();
if($entity instanceof BackendUser) {
$this->preUpdateBackendUser($entity);
}
}
/**
* @param BackendUser $be_user
*/
private function preUpdateBackendUser(BackendUser &$be_user) {
$plain_password = $be_user->getPlainPassword();
if(!empty($plain_password)) {
$new_password = $this->passwordEncoder->encodePassword($be_user, $plain_password);
$be_user->setPassword($new_password);
$be_user->setPlainPassword();
}
}
}