斯卡拉的链接期货

时间:2018-01-06 01:21:06

标签: scala future

考虑一下:

val f1 = Future {}

val f2 = Future {}

f1.flatMap(_ => f2)

在这种情况下,f2完成之前f1是否可能完成?

我怀疑是的。

那我怎么能解决这个问题呢?我的意思是,如何才能确保f2仅在f1完成后启动?

这会有效/(做好风格):

def f1 = Future {}

def f2 = Future {}

f1.flatMap(_ => f2)

2 个答案:

答案 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();
        }
    }
}