当前位置: 首页 > 知识库问答 >
问题:

第一个for回调几乎每次都打印未来列表,第二个onComplete回调很少返回成功(从不失败)

杨腾
2023-03-14

我在看一些未来的例子。我有一个从方法中获取列表的未来。我调用了两种不同类型的回调,Foreach回调和onComplete回调,只是为了尝试一下。

  • Foreach回调几乎每次都返回列表。
  • 即使For回调返回了列表,on完成回调也很少返回SUCCESS。
  • on完成回调永远不会返回FAILURE。

有人能给我解释一下发生了什么吗?

我知道回调是并发执行的,没有顺序。但是如果Future正在将列表返回给Foreach,而onComplete回调已经在Foreach和Future之前执行,并且它试图从一个不成功的Future获取列表,那么onComplete回调不应该返回失败吗?

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}

object FuturesExampleObj extends App {

  println("Using Future to retrieve list\n")
  val l: Future[List[String]] = Future {
    getList()
  }

  println("FOR CALLBACK --------------------\n")

  l foreach {
    items =>
      for(item <- items) println(s"foreach item : $item")
      println("\n")
  }

  println("onComplete CALLBACK --------------------\n")

  l onComplete {
    case Success(i) => println(s"SUCCESS : $i")
    case Failure(i) => println(s"FAILURE : $i")
  }

  def getList(): List[String] ={
    val list = ("a" :: "b" :: "c" :: "d" :: "e":: Nil)
    list
  }
}

结果示例1(通用)

Using Future to retrieve list

FOR CALLBACK --------------------

onComplete CALLBACK --------------------

foreach item : a
foreach item : b
foreach item : c
foreach item : d
foreach item : e



Process finished with exit code 0

结果示例2(不常见)

Using Future to retrieve list

FOR CALLBACK --------------------

onComplete CALLBACK --------------------


Process finished with exit code 0

结果示例3(非常罕见)

基本上,onComplete 从不返回成功或失败。有时,很少会返回“SUCCESS:”列表。

共有2个答案

马博学
2023-03-14

原因是应用程序线程在“未来”完成之前完成。

只需添加Await.ready(l,Duration.Inf)。value.get

这样做只是为了测试!

端木狐若
2023-03-14

这是因为你必须明确地阻止未来。在您的情况下,主线程在<code>onComplete</code>完成之前终止,有时在<code>l foreach..完成之前终止。

请补充:

import scala.concurrent.{Await, Future}
import scala.concurrent.duration._

val listF = l foreach {
  items =>
    for(item <- items) println(s"foreach item : $item")
    println("\n")
}

Await.result(listF, 5 seconds)

这样,您将等待这个未来的完成。

如果您想等待on完成,您需要使用Thread.sleep(在on完成之后添加它,例如:

l onComplete {
   case Success(i) => println(s"SUCCESS : $i")
   case Failure(i) => println(s"FAILURE : $i")
}

Thread.sleep(3000)

onComplete 在 ExecuteContext 中的某个线程上运行,而 Await 在当前线程上运行,并阻止它,直到它完成或超过指定的超时。因此,onComplete 是非阻塞的,而 Await 是阻塞的。

使用< code>onComplete时,我们不会阻止来自< code>Future的结果,而是会收到一个< code >成功或< code >失败的回调。

< code>Thread.sleep()正在阻塞我们的主线程,以便我们可以看到未来的异步结果。

请注意,您不应该在生产代码中使用< code>Await.result,它用于测试未来的输出。此外,您肯定不会使用< code>Thread.sleep(),而是对未来返回的结果做出“反应”。

通常,您将有一些REST API调用或其他服务运行并等待将来完成。

 类似资料:
  • 在第一章中,我们探讨了JavaScript中关于异步编程的术语和概念。我们的焦点是理解驱动所有“事件”(异步函数调用)的单线程(一次一个)事件轮询队列。我们还探讨了各种解释 同时 运行的事件链,或“进程”(任务, 函数调用等)间的关系的并发模式。 我们在第一章的所有例子中,将函数作为独立的,不可分割的操作单位使用,在这些函数内部语句按照可预知的顺序运行(在编译器水平之上!),但是在函数顺序水平上,

  • 尝试拯救回调 有几种回调的设计试图解决一些(不是全部!)我们刚才看到的信任问题。这是一种将回调模式从它自己的崩溃中拯救出来的勇敢,但注定失败的努力。 举个例子,为了更平静地处理错误,有些API设计提供了分离的回调(一个用作成功的通知,一个用作错误的通知): function success(data) { console.log( data ); } function failure(er

  • 我用的是parse.com。每个包里面都有很多钻子,每个品类里面都有很多包。 我卡住了。然后(函数(result,result2,result3)在最后一行。promise可以有多个promise,它是可变的。有没有一种方法可以写出如下内容: 谢谢!

  • 复习 回调是JS中异步的基础单位。但是随着JS的成熟,它们对于异步编程的演化趋势来讲显得不够。 首先,我们的大脑用顺序的,阻塞的,单线程的语义方式规划事情,但是回调使用非线性,非顺序的方式表达异步流程,这使我们正确推理这样的代码变得非常困难。不好推理的代码是导致不好的Bug的不好的代码。 我们需要一个种方法,以更同步化,顺序化,阻塞的方式来表达异步,正如我们的大脑那样。 第二,而且是更重要的,回调

  • 延续 让我们回到在第一章中开始的异步回调的例子,但让我稍微修改它一下来画出重点: // A ajax( "..", function(..){ // C } ); // B // A和// B代表程序的前半部分(也就是 现在),// C标识了程序的后半部分(也就是 稍后)。前半部分立即执行,然后会出现一个不知多久的“暂停”。在未来某个时刻,如果Ajax调用完成了,那么程序会回到它刚才离开的

  • 我正在使用JavaFx对GUI进行编程,我真的不知道如何连接所有内容。我有一个主窗口,在主窗口中我有一个按钮可以打开另一个窗口,允许我选择客户。现在我已经在努力将选定客户的信息返回给主窗口,因为我没有打开它的返回方法。 我是这样打开的:public void openSecondWindow(ActionEvent事件){ 我自己没有初始化第二个窗口,也没有像第二个窗口sc=new第二个窗口()这