我使用BreezeJS来处理ng-grid的服务器端过滤。为此,我只需$watch
更改ng-grid过滤器,并使用BreezeJS刷新我的数据。如果我输入的速度足够快,那么AJAX查询最终可能会出现故障。
我正在考虑将GUID与每个查询相关联(通过闭包),并跟踪上次发出的查询请求的GUID。然后忽略返回的任何与GUID不匹配的查询(我不需要过时的查询结果 - 只是最新的)。
但是有没有更好或更惯用的处理方法,特别是在Angular / Breeze中?
答案 0 :(得分:6)
@Adam对您的主要问题提出了一个重要的想法...在用户在搜索框中输入时,您可以解决一系列问题。
你应该"去抖" (AKA,"油门")开始取消请求之前的搜索条目。这意味着在向服务器发出查询之前,等待用户停止输入。
在网上搜索" Angular"和#34;去抖"而且你会发现许多技巧。我使用的是将搜索框绑定到ngChanged=vm.searchChanged()
。然后,ViewModel的searchChanged
方法将启动$timeout
。如果用户在1/2秒内输入任何内容,我将取消该超时并启动另一个超时。在沉默500毫秒后,我开始查询。我也会立即开始模糊或者按下回车键。
当Angular v.1.3发布时(很快就会发布)," debounce"将成为Angular绑定的一部分。我期待着破坏我自制的辩护代码。
想象一下,用户停止键入500毫秒,查询开始,......并且不耐烦的用户想要取消请求。她不能在Breeze v.1.4.11中做到这一点。她将能够在第6.1.12节。
我刚刚为jQuery和Angular扩展了Breeze AJAX适配器,以便在响应another question of yours时促进取消和超时。
在其他情况下,您可以启动多个请求。答案不一定按照您的请求顺序到达。这就是异步的本质。
你绝对可以自己保持秩序。请记住,您构造了回调。您可以维护一个应用程序范围的请求计数器,为每个查询和保存添加...然后在回调中引用。
我在DocCode:queryTests.js中写了一个说明性示例,其中显示了一种方法:
/*********************************************************
* Dealing with response order
* It's difficult to make the server flip the response order
* (run it enough times and the response order will flip)
* but the logic of this test manifestly deals with it
* because of the way it assigns results.
*********************************************************/
asyncTest("can sequence results that arrive out of order", 3, function() {
var nextRequestId = 0;
var em = newEm();
var promises = [];
var results = [];
var arrived = [];
promises.push(breeze.EntityQuery.from('Customers')
.where('CompanyName', 'startsWith', 'a')
.using(em).execute()
.then(makeSuccessFn()).catch(handleFail));
promises.push(breeze.EntityQuery.from('Customers')
.where('CompanyName', 'startsWith', 's')
.using(em).execute()
.then(makeSuccessFn()).catch(handleFail));
function makeSuccessFn() {
var requestId = nextRequestId++;
return function success(data) {
// Don't know which response arrived first?
// Sure you do. Just refer to the requestId which is a capture
arrived.push(requestId);
results[requestId] = data.results;
assertWhenDone();
}
}
function assertWhenDone() {
if (results[0] && results[1]) {
start(); // we're done
// Here we report the actual response order
ok(true, "Request #{0} arrived before #{1}".format(arrived[0], arrived[1]));
// no matter what the response order
// the 'a' companies go in results slot #0
// the 's' companies go in results slot #1
var aCompany = results[0][1].CompanyName();
var sCompany = results[1][1].CompanyName();
equal(aCompany[0].toLowerCase(), 'a',
"company from first batch should be an 'a', was " + aCompany);
equal(sCompany[0].toLowerCase(), 's',
"company from second batch should be an 's', was " + sCompany);
}
}
});
我应该提到all
promises方法将响应数组传递给保留请求顺序的then(...)
成功回调。如果您碰巧在同一个地方同时发出多个查询并且可以一起等待它们(如上例所示),那么您不需要requestId
的所有繁重工作。就这样做......
var promises = [];
promises.push(breeze.EntityQuery.from('Customers')
.where('CompanyName', 'startsWith', 'a')
.using(em).execute();
promises.push(breeze.EntityQuery.from('Customers')
.where('CompanyName', 'startsWith', 's')
.using(em).execute();
// Q.all waits until all succeed or one of them fails
// breeze.Q is typically $q in an Angular app
breeze.Q.all(promises).then(allSucceeded).catch(atLeastOneFail);
function allSucceeded(responses) {
// response[0] is from the first 'a' query regardless of when it finished.
// response[1] is from the second 's' query regardless of when it finished.
}
答案 1 :(得分:1)
在用户输入时取消之前的任何请求,这样,只有当前请求的响应才会更新结果。
仅限伪代码:
var req;
function search(searchTerm) {
req && req.cancel();
req = queryServer().then(resultsReturned);
}
function resultsReturned() {
}