2017-02-09 28 views
0

Во-первых, это не проблема в Grails 2.5.4.В Grails 3.2.4 контроллер, у которого есть вызов .async.task, устанавливает request.asyncStarted() в true, но не возвращает ответ

Я делаю угловой вызов AJAX моему контроллеру Grails, и контроллер 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 немедленно вернуться, и просто отлично. Это конечная точка, однако, имеет два async.task, и я могу сказать, флаг asyncStarted в настоящее время запускается после первого async.task определяется:

 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() возвращает ложь, а второй возвращает истину , Я был предупрежден, чтобы это быть проблемой асинхронной когда я повернул протоколируемой весь путь вверх и заметил это сообщение в моих журналах:

2017-02-08 18:47:54 DEBUG ogweb.servlet.mvc .GrailsDispatcherServlet: Оставляя ответ открытым для параллельной обработки

Ранее в Grails 2.5.4 я просто должен был просто назвать availabilityTask.get() и сделать вид с соответствующей моделью и макетом указанной. Теперь, оказывается, что я должен сделать это для того, чтобы получить ответ на смывать назад к переднему концу:

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

Это кажется раздражает, так как я не пропуская никаких обещаний или вызываемых объектов в модели и Я уже проверяю, что задачи завершены. Мне не хватает чего-то, что заставляет меня это делать, или это ожидаемое и плохо документированное поведение (не вызвало нигде в документе Grails о Async, что .dispatch() необходимо вызвать для сброса асинхронных запросов.

UPDATE февраля, десятые 2017

Я попытался пройти обещание в модели, как:

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

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

, полагая, что в результате трансформатор будет обнаружить Promise в модели, но авто-диспетчерская Ждут» я думал, чтобы имитировать то, что я видел в документации Grails Async b ut Я предполагаю, что вся модель должна быть PromiseMap, чтобы произошла автоматическая отправка? (Который не является идеальным, когда у меня есть контроллер тяговое синхронной и асинхронной передачи данных)

раздел из документации:

import static grails.async.Promises.* 

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

Во всяком случае, кажется, сейчас мой вариант, чтобы обернуть контроллеры с любым * .async. задачи в более крупной задаче {} закрытия или вручную управлять рассылкой.

ответ

1

Верно, что Grails ранее не начинал и не запрашивал асинхронные запросы. Такое поведение было неправильным, потому что если задача заняла некоторое время, первоначальный запрос мог быть завершен и возвращен в пул потоков до того, как задача успеет завершить, что приведет к непредсказуемому поведению и исключениям.

Такое поведение было исправлено в Grails 3. Если вы возвращаете Promise созданный методом task из контроллера, то Grails автоматически обрабатывать призвание dispatch() для вас.Вы можете видеть это здесь 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

+0

Привет, Грэм, благодарю вас за ответ. Когда вы упоминаете, что ранее «если задача заняла время», я согласен и считаю, что я был обязан называть .get или Promises.waitAll для обеспечения выполнения моих задач. Когда я впервые начал использовать async-задачи, я столкнулся с проблемами, в которых я не понимал, что должен был это сделать, и получил бы асинхронные нулевые ошибки (как вы упомянули). Я отредактировал свой вопрос с обновлением, чтобы показать, как я также пытался передать Promise в модель, и он не обнаружил это и автоматически отправил этот путь либо. Это единственный способ обернуть все это в задачу {}? –

+0

Я отмечу это как ответ, поскольку он по крайней мере проясняет поведение/ожидание больше, чем документация, которая была моей реальной вызывающей проблемой/путаницей. –