[英]How to listen to async server side Java Controller?
仔細研究這個例子,我遇到了很多例子,其中之一是來自Angular的$ q,以避免遞歸地訪問我的服務器端以檢查請求是否包含數據。
我碰到了這個鏈接: 遞歸$ http.get for循環
建議使用$ q,但我認為這不會解決我的問題。
JS:
function OrderFormController($scope, $http, $q) {
$('#loaderImage').show();
$http.get('/utilities/longProcess')
.success(function(data, status, headers, config) {
if(data != 'Still Processing'){
console.log('Data from server');
$scope.sampleJSON = data.pmdStructureWrapper;
$scope.sampleJSONDuplicates = data.pmdDuplicates;
$scope.$watch('sampleJSON', setTimeout(function() {
$('.panel-body li').each(function() {
if ($.trim($(this).text()) === "") {
$(this).hide();
}
});
}, 1000));
$('#loaderImage').hide();
}else{
console.log('rejected');
$q.reject(data);
}
})
.error(function(data, status, header, config) {
});
}
控制器:
@RequestMapping("/utilities/longProcess")
public CompletableFuture<String> asyncLongProcess(HttpServletResponse response, HttpServletRequest request) {
HttpSession session = request.getSession();
return CompletableFuture.supplyAsync(() -> session.getAttribute("CACHED_RESULT"))
.thenComposeAsync(obj -> {
if (obj == null) {
if(session.getAttribute("BACKGROUND_PROCESSING") == null) {
session.setAttribute("BACKGROUND_PROCESSING", true);
CompletableFuture.supplyAsync(() -> callURL(response, request))
.thenAccept(result -> session.setAttribute("CACHED_RESULT", result));
}
return CompletableFuture.completedFuture("Still Processing");
}
return CompletableFuture.completedFuture(obj.toString());
});
}
HTML:
<body ng-app ng-controller="OrderFormController">
<header>
<div class="container">
<div id="branding">
<h1><span class="highlight">Review </span> Result</h1>
<form class="form-logout" role="form" action="/logout">
<input type="submit" value="Logout" id="logout" class="btn btn-primary btn-lg pull-right">
</form>
</div>
</div>
</header>
<img src="../img/spinner.gif" id="loaderImage" style='display:none'>
<div class="col-md-12 col-lg-12" ng-cloak="">
<div class="panel with-nav-tabs panel-default">
<div class="panel-heading">
<ul class="nav nav-tabs">
<li class="active"><a href="#tab1default" data-toggle="tab">Classes</a></li>
<li><a href="#tab2default" data-toggle="tab">Triggers</a></li>
<li><a href="#tab3default" data-toggle="tab">Visualforce pages</a></li>
<li><a href="#tab4default" data-toggle="tab">Duplicate Codes</a></li>
</ul>
</div>
<div class="panel-body">
<div class="tab-content">
<div class="tab-pane fade in active" id="tab1default">
<ul class="col-md-12 col-lg-12">
<li ng-click="showErrorDetails(key)" class="col-sm-12 col-md-4 col-lg-4 eachClassCell"
ng-repeat='(key,value) in sampleJSON'>
<div ng-if="key.indexOf('.cls') > -1">
<div title="{{key}}" class="classNameLabel">{{key}}</div>
<div title="Error count" class="errorContainer">
<span class="errorCount">{{value.pmdStructures.length}}</span>
<span class="errorMeter"
ng-repeat="eachClass in value.pmdStructures | limitTo: 10"></span>
</div>
</div>
</li>
</ul>
</div>
<div class="tab-pane fade" id="tab2default">
<ul class="col-md-12 col-lg-12">
<li ng-click="showErrorDetails(key)" class="col-sm-12 col-md-4 col-lg-4 eachClassCell"
ng-repeat='(key,value) in sampleJSON'>
<div ng-if="key.indexOf('.trigger') > -1">
<div title="{{key}}" class="classNameLabel">{{key}}</div>
<div title="Error count" class="errorContainer">
<span class="errorCount">{{value.pmdStructures.length}}</span>
<span class="errorMeter"
ng-repeat="eachClass in value.pmdStructures | limitTo: 10"></span>
</div>
</div>
</li>
</ul>
</div>
<div class="tab-pane fade" id="tab3default">
<ul class="col-md-12 col-lg-12">
<li ng-click="showErrorDetails(key)" class="col-sm-12 col-md-4 col-lg-4 eachClassCell"
ng-repeat='(key,value) in sampleJSON'>
<div ng-if="key.indexOf('.page') > -1">
<div title="{{key}}" class="classNameLabel">{{key}}</div>
<div title="Error count" class="errorContainer">
<span class="errorCount">{{value.pmdStructures.length}}</span>
<span class="errorMeter"
ng-repeat="eachClass in value.pmdStructures | limitTo: 10"></span>
</div>
</div>
</li>
</ul>
</div>
<div class="tab-pane fade" id="tab4default">
<ul class="col-md-12 col-lg-12">
<li ng-click="showDuplicateDetails(eachValue)" class="col-sm-12 col-md-4 col-lg-4 eachClassCell"
ng-repeat='eachValue in sampleJSONDuplicates'>
<div title="{{eachValue.duplicationInFile}}" class="classNameLabel">
{{eachValue.duplicationInFile}}
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<form>
</form>
<footer>
<p>Salesforce Free Code Review, Copyright © 2017</p>
</p>
</footer>
<script type="application/javascript">
</script>
</body>
這樣做是為了避免超時,它將超時Still Processing
消息發送到客戶端,因為超時限制為30000ms,因此我知道首先想到的是每個請求進行30個數據的延遲加載,但是相信我不能。
我已經構建了一個代碼審查工具,因此當URL被命中時,它將使用后台線程對所有類運行代碼審查,然后在大約CompletableFuture
秒后在CompletableFuture
返回響應。 直到再次刷新頁面,客戶端才知道此響應。
即使刷新頁面后,由於數據超過7MB,該頁面仍需要花費近13-35秒才能顯示結果。
該代碼在本地環境下工作正常,但是當我在共享服務器heroku上托管時,我開始超時。 有兩個問題:
1)angularJS如何檢測RestAPI響應的變化?(由於將發送兩個響應,第一個響應是“ Still Processing”的即時響應,第二個是實際結果。這是我必須使用的響應)。
2)如何從Controller延遲加載JSON格式的數據?
更新1:
我也嘗試使用OutputStream:
控制器:
@RequestMapping("/utilities/longProcessStream")
public StreamingResponseBody asyncLongProcessStream(HttpServletResponse response, HttpServletRequest request) {
return new StreamingResponseBody() {
@Override
public void writeTo(OutputStream outputStream) throws IOException {
PMDController.this.callURL(response, request, outputStream);
}
};
}
但是現在響應更改為XML和JS console.log('Data from server');
直到從服務器端收集到完整響應后,才會打印行。
當響應更改為XML時,由於完整的JS依賴於JSON,如何將其解析為JSON格式?
流式傳輸后,為什么在完整請求完成后角度顯示結果呢?
我發現一個讀取StreamingBodyResponse的庫,它們在內部將blob類型更改為JSON,這正是我需要的:
@RequestMapping("/utilities/longProcessStream")
public StreamingResponseBody asyncLongProcessStream(HttpServletResponse response, HttpServletRequest request) {
response.addHeader("Content-Type", MediaType.APPLICATION_JSON);
return new StreamingResponseBody() {
@Override
public void writeTo(OutputStream outputStream) throws IOException {
PMDController.this.callURL(response, request, outputStream);
}
};
}
JS:
$('#loaderImage').show();
$scope.sampleJSONClass = {};
$scope.sampleJSONTrigger = {};
$scope.sampleJSONPages = {};
oboe('/utilities/longProcessStream')
.done(function(data) {
var dataFromServer = data.pmdStructureWrapper;
if (Object.keys(dataFromServer)[0].endsWith('.cls')) {
$scope.sampleJSONClass[Object.keys(dataFromServer)[0]] = Object.values(dataFromServer)[0];
}
if (Object.keys(dataFromServer)[0].endsWith('.trigger')) {
$scope.sampleJSONTrigger[Object.keys(dataFromServer)[0]] = Object.values(dataFromServer)[0];
}
if (Object.keys(dataFromServer)[0].endsWith('.page')) {
$scope.sampleJSONPages[Object.keys(dataFromServer)[0]] = Object.values(dataFromServer)[0];
}
$scope.$apply();
$('#loaderImage').hide();
})
.fail(function() {
console.log('error');
});
這很完美。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.