在 Grails 3.2.4 中,具有 .async.task 调用的控制器将 request.asyncStarted() 设置为 true 但不呈现响应

In Grails 3.2.4, controller that has an .async.task call in it sets request.asyncStarted() to true but doesn't render response

首先,这在 Grails 2.5.4 中不是问题。

我正在向我的 Grails 控制器发出 angular AJAX 调用,但 Grails 控制器从未响应。前端调用看起来像这样..

     $http({
            method: "GET",
            url: actionLink,
            params: {}
        }).then(function successCallback(response) {

            console.log("Yaaay, I got back with some sort of response");
        }, function errorCallback(response) {
            console.log("ERROR PULLING DETAIL")
        });

我已经确认 AJAX 对其他控制器的调用不会立即调用任何类型的 .async.task return,而且很好。然而,这个终点有两个 async.task,我可以看出在定义第一个 async.task 后触发了 asyncStarted 标志:

        log.info("ASYNC CHECK-1 - asyncSupported=" + request.asyncSupported + ", asyncStarted=" + request.isAsyncStarted())

        def availabilityTask = Item.async.task {

            JSON availability = itemService.getItemAvailabilityAsJSON(itemInstance)

            availability
        }

        log.info("ASYNC CHECK-2 - asyncSupported=" + request.asyncSupported + ", asyncStarted=" + request.isAsyncStarted())

第一个 request.isAsyncStarted() return 为假,第二个 return 为真。当我一直打开日志记录并在我的日志中注意到这条消息时,我被告知这是一个异步问题:

2017-02-08 18:47:54 DEBUG o.g.web.servlet.mvc.GrailsDispatcherServlet : Leaving response open for concurrent processing

以前在 Grails 2.5.4 中,我只需调用 availabilityTask.get() 并使用指定的适当模型和布局渲染视图。现在看来,我必须这样做才能让响应刷新回前端:

   if (request.isAsyncStarted()) {
            final AsyncContext ac = request.asyncContext;
            log.info("Calling to complete async request")
            ac.dispatch()
   }

这看起来很烦人,因为我没有将任何承诺或可调用项传递到模型中,而且我已经在检查任务是否已完成。我是否遗漏了一些迫使我这样做的东西,或者这是预期的且记录不完整的行为(在 Grails 文档的任何地方都没有提到需要调用 .dispatch() 来刷新异步请求的 Async ..

2017 年 2 月 10 日更新

我试图将承诺传递到模型中,例如:

        def availabilityTask = Item.async.task {
            JSON availability = itemService.getItemAvailabilityAsJSON(itemInstance)

            availability
        }
        render view : "myView", model:[nonAsyncItems, availabilityTask]

认为结果转换器会检测到模型中的 Promise,但没有发生自动调度。我想模仿我在 Grails Async 文档中看到的内容,但我想整个模型必须是 PromiseMap 才能进行自动调度? (当我有一个控制器拉取同步和异步数据时,这并不理想)

文档部分:

    import static grails.async.Promises.*

    def index() {
       render view:"myView", model: tasks( one:{ 2 * 2 },
                                           two:{ 3 * 3 } )
    }

无论如何,现在我的选择似乎是将控制器与任何 *.async.task 包装在一个更大的任务 {} 闭包中,或者手动管理调度。

确实Grails以前没有启动和异步请求任务。这种行为是错误的,因为如果任务需要时间,那么原始请求可能会在任务有时间完成之前完成并 returned 到线程池,从而导致不可预测的行为和异常。

此行为已在 Grails 3 中得到纠正。如果您 return 通过控制器的 task 方法创建的 Promise,Grails 将自动处理 [=12= 的调用] 为你。你可以在这里看到这个 https://github.com/grails/grails-core/blob/3.2.x/grails-plugin-async/src/main/groovy/org/grails/plugins/web/async/mvc/AsyncActionResultTransformer.groovy#L72