2015-12-10 105 views
0

我想在Grails中利用多線程來處理AJAX調用。該網頁觸發AJAX調用,控制器分配一個新線程完成該任務,並在完成時返回並呈現結果。這是我的嘗試。它失敗了。貌似第二個AJAX調用並沒有被解僱。Grails使用Promises來回答AJAX調用

在gsp中的javascript:兩個AJAX調用。第一個完成時觸發第二個。

function asynchroCrawl(){ 
    var jsonData = $.ajax(
      { 
       url : "${createLink(controller:'environment', action:'asynchroCrawl')}", 
       dataType : "json", 
       async : true 
      }).done(function(jsonData) { 
       console.log("Crawler completed"); 
       crawlFinished=true; 
       asynchroWordCloud(); 
    }); 
} 
function asynchroWordCloud() { 
    var jsonData = $.ajax(
        { 
         url : "${createLink(controller:'environment', action:'asynchroKeywords')}", 
         dataType : "json", 
         async : false 
        }).done(function(jsonData) {      
       keywordFinished = true; 
      }); 
} 

在控制器中:另一個acton功能被省略。

def asynchroCrawl={ 
    User u=session.getAttribute("user"); 
    FrameworkController.crawlStarted=true; 
    println "Crawling task started."; 
    def p=task{ 
     NetworkGenerator.formNetwork(u); 
    } 
    p.onError { Throwable err -> println "An error occured \n${err.message}" } 
    p.onComplete { result -> 
     println "User crawl complete."; 
     FrameworkController.crawlComplete=true; 
     render u as JSON; 
     return; 
    } 
} 

NetworkGenerator僅僅是運行一些工作並更新User.withTransaction{u.merge();}

我的理解用戶對象是一個承諾創建和處理我的工作,這是完成時,該數據應正常類返回到迴應AJAX呼叫的網頁。所以.done()函數也應該被觸發,導致流向另一個AJAX調用。但是,從不觸發done()。我在瀏覽器控制檯中看不到「履帶完成」。

在我的IDE控制檯中,我確實看到「用戶爬網完成」,表示承諾已完成。但有一個例外如下,說:

2015-12-10 21:05:47,540 [Actor Thread 7] ERROR gpars.LoggingPoolFactory - Async execution error: null 
Message: null 
Line | Method 
->> 1547 | notifyAttributeAssigned in org.apache.catalina.connector.Request 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
| 1538 | setAttribute   in  '' 
| 541 | setAttribute . . . . . in org.apache.catalina.connector.RequestFacade 
| 288 | setAttribute   in org.apache.catalina.core.ApplicationHttpRequest 
| 431 | storeGrailsWebRequest . in org.codehaus.groovy.grails.web.util.WebUtils 
|  61 | doCall     in org.codehaus.groovy.grails.plugins.web.async.WebRequestPromsiseDecorator$_decorate_closure1 
|  -1 | call . . . . . . . . . in  '' 
|  61 | doCall     in org.grails.async.factory.gpars.GparsPromise$_onComplete_closure1 
|  -1 | call . . . . . . . . . in  '' 
|  62 | run      in groovyx.gpars.dataflow.DataCallback$1 

請有人可以告訴我我在做什麼錯在這裏。非常感謝您的幫助!

+0

這不是它的工作原理。請求已在此刻處理完畢。你必須在那裏做出響應(或使用Servlet 3.0異步,但無論如何,我不知道它如何幫助你)。只是從服務器動作中刪除異步代碼,你不需要它,它也沒有任何意義 –

+0

,像'FrameworkController.crawlStarted = true'使你的控制器非線程安全,你不應該存儲用戶狀態共享變量(控制器類只有一個實例,在多個請求之間共享) –

+0

@IgorArtamonov只有當設置了'static scope ='singleton''時,纔會這樣。每默認每個請求都會創建一個新的控制器實例所以它可以放在 – injecteer

回答

0

每個servlet請求已經在一個線程內提供服務,所以不需要產生另一個線程。你可以在行動中產生一個新的線索 - 或者與new Thread().start()或與GPars - 並不重要。

要緊的是,你必須等待(與thread.join()或類似),直到線程完成,讓你的行動可以提供的結果您的JS代碼預計

+0

感謝injecteer我不知道它!這就是爲什麼我試圖自己實現多線程。 – OrlandoL