所以我正在为客户建立一个网站。在我们的搜索页面上,我正在观看搜索栏,每个按键都会触发一个新的搜索请求,以便在您输入时更新结果。我的问题是,当我快速输入搜索字词时,服务器可以“赶紧”#hieup'并且没有按照我要求的顺序返回我的结果。这只会导致绑定到返回数据的某些标记显示错误的值。例如。如果我输入单词" video"。 99%的时间我得到了正确的结果,我的所有标签看起来都是正确的。然而,1%的时间,我搜索" vide"在我搜索"视频"之后将返回这会导致它显示错误的结果和错误的总数。遗憾的是,由于不公开协议,我无法链接现场演示,但我可以发布使其运行的代码。我们处于生产的后期阶段,因此让它尽快正常运行比使用最佳实践更重要。 html的一些部分:
<h1>Search</h1>
<p ng-cloak class="results-message fade-in">
<span ng-if="items.loaded && term">{{total}} results for "{{term}}" </span>
<span ng-if="!total && !term">No query was entered </span>
<span ng-if="!items.loaded && term">Searching...</span>
</p>
<div class="search-container">
<input type="search" name="term" value="asd" ng-init="term='asd'" ng-model="term" placeholder="Enter your search term" ng-keydown="$event.keyCode == 13 ? $event.preventDefault() : 0;" class="search">
<input type="image" name="submit" src="/_res/astoncarter/img/images/search-icon.gif" alt="Submit">
</div>
</div>
<ul ng-cloak ng-class="{loading: loading}" class="results">
<li ng-if="items.loaded && !items.length && term" class="fade-in">
<h2>No results were found for {{term}}</h2>
</li>
<li ng-if="!term" class="fade-in">
<p class="text-center">Please enter a search query</p>
</li>
<li ng-repeat="item in items" class="fade-in">
<h2><a href="{{item.url}}">{{item.title}}</a></h2>
<p>{{item.teaser}}</p>
</li>
</ul>
</div>
</div>
</div>
<p ng-if="count == 10" class="load-more"><a href="" ng-if="!loading" ng-click="loadQuery()" class="btn">Load More</a><a href="" ng-if="loading" disabled class="btn"><i class="fa fa-spinner fa-spin"> </i> LOAD</a></p>
JS:
app.controller('ListingCtrl', function ($scope, $element, $timeout, acAPIservice, $location, $interval) {
// Grabbing and using the attribute from the dom is not the Angular way
// but a compromize if we want BE developers to be able to set the API
// Other options would be to set a global variable to be output and used
$scope.apiUrl = $element.attr('data-api-url');
$scope.pageSize = $element.attr('data-page-size');
$scope.language = $element.attr('data-language');
$scope.timer = 3;
$scope.term = undefined;
$scope.items = [];
$scope.start = 0;
$scope.end = 0;
$scope.total = 0;
$scope.loading = false;
// main worker to get data
// lists that need data should call this on ng-init
$scope.loadQuery = function(){
$scope.loading = true;
var payload = {
pageSize : $scope.pageSize,
start : $scope.end+1,
language : $scope.language
};
if($scope.term) {
payload.term = $scope.term
}
acAPIservice.getSearch($scope.apiUrl, payload) //this just hits a factory with the url and payload and returns the data object
.success(function (data) {
$scope.timer = 3; //reset the timer
$scope.items = $scope.items.concat(data.results);
$scope.start = data.start;
$scope.end = data.end;
$scope.total = data.total;
$scope.loading = false;
$scope.items.loaded = true;
$scope.count = data.count;
})
.error(function(data, status, headers, config){
$scope.items = [];
$scope.items.loaded = true;
});
};
// cheating a bit here. We let the ng-init attribute for term trigger
// the first batch. Also grabs new batches when term is updated
$scope.$watch('term', function(newValue, oldValue) {
// reset everything
$scope.items = [];
$scope.start = 0;
$scope.end = 0;
$scope.total = 0;
// if we still have a search term go get it
if($scope.term){
$scope.loadQuery();
//because you can't turn off async in angular we need to set a timer that gets reset every time you load a query. After 1 second we recall to make sure our total reflects the accurate num
var promise = $interval( function(){
$scope.timer = $scope.timer-1;
if($scope.timer === 0){ //if the timer runs out it means that no terms have been entered in 1 second, which we will then cancel the interval and and do one last load
$interval.cancel(promise);
$scope.loadQuery();
}
}, 500);
}
});
});
它始终显示正确的搜索词,但它会显示最后返回的{{total}},并且似乎将最后2个返回的结果附加在一起。
我只是尝试实施间隔来排序&#34;刷新&#34;在没有用户输入的情况下经过一秒钟后的结果,但有时服务器可能需要超过1秒,这意味着它仍将使用错误的信息进行更新。如果你需要我澄清一些问题,请问我任何问题。我有时很难解释我的问题。同样抱歉格式化:(
答案 0 :(得分:0)
只需返回搜索结果中的文本即可。当promise被解决时,如果返回的文本不等于当前文本,则返回函数。
acAPIservice.getSearch($scope.apiUrl, payload)
.success(function (data) {
if (data.term !== $scope.term) {
return;
}
$scope.timer = 3; //reset the timer
$scope.items = $scope.items.concat(data.results);
$scope.start = data.start;
$scope.end = data.end;
$scope.total = data.total;
$scope.loading = false;
$scope.items.loaded = true;
$scope.count = data.count;
})
.error(function(data, status, headers, config){
$scope.items = [];
$scope.items.loaded = true;
});
答案 1 :(得分:0)
要解决未成熟搜索结果的问题,请使用debounce:
ng-model-options="{ debounce: 1000 }"
在此示例中,它将查询延迟发送到1000毫秒。因此,您将获得&#34;视频&#34;的结果。而不是&#34; vide&#34;