[英]Cannot break recursion with $.Deffered() object and $.then()
我必须搜索可能有数十万行的单词索引表。 我可以通过将文档列表传递给搜索来限制搜索。 在许多文档中搜索单词的请求返回非常缓慢。 所以...为了改善UX,我们将请求分块成几组文档。 因此,如果用户要求搜索90个文档,而每个查询的块大小为10个文档,则我们发出90/10 = 9个独立的$ .ajax()调用。 我们希望结果按发送顺序排列。
var SearchFunction = function () {
$.ajax(/* ... */);
}
var RecursiveSearch = function () {
var deferred = $.Deferred();
if (arrTransSearch.length > 0) {
deferred = SearchDocuments(arrTransSearch.shift());
}
else {
deferred.reject();
}
return deferred.promise().then(RecursiveSearch);
}
if (arrTransSearch.length > 1) {
RecursiveSearch().fail(SomeFunction);
}
var SomeFunction = function () {
alert("Failed. Yes!");
}
当我调试代码时, 似乎 deferred.reject()
不会更改deferred.promise()
的状态。 也就是说,当下一行
return deferred.promise().then(RecursiveSearch)
执行后,它只是循环回到递归函数中,而不是退出递归并陷入
RecursiveSearch().fail(SomeFunction);
我正在使用jQuery-1.7.1 。 我在JSFiddle中运行了类似的递归(谢谢Beeetroot-Beetroot ),它在jQuery-1.7.2上失败了,而在jQuery-2.1.0上却没有问题。
关于如何使递归在jQuery-1.7.1中工作的任何想法吗?
在标题“ The Kerfuffle Collection”下,提供了部分覆盖您所寻找内容的模式。 实际上,您实际需要的略多于此,这是因为您想以块(组)形式寻址文档引用列表。
该代码将是这样的:
$(function() {
//General ajax options for searching a document group
var ajaxOptions = {
url: '...',
type: 'POST',
//data: ... //added dynamically
dataType: 'JSON',
// etc.
};
//
function searchDocumentsInGroups(arr, n) {
//Pre-process arr to create an array of arrays, where each inner array is a group of document references
var groups = [];
$.each(arr, function (i) {
if (!(i % n)) groups.push(arr.slice(i, i + n));
});
//Ajax serializer (from the Collection Kerfuffle reference)
return groups.reduce(function (promise, group) {
return promise.then(function () {
return $.ajax($.extend({}, ajaxOptions, {
data: JSON.stringify(group);//or whatever, compatible with the server-side script
})).then(function (groupResults) {
//display groupResults here
});
});
}, $.when(0));
}
// data
var myDocumentArray = [ 'doc1', 'doc2', 'doc3', 'doc4', 'etc.' ], //Your array of 90 document references.
groupSize = 10; //Number of documents per "chunk".
// Event handler to kick off the process.
$("#searchDocuments").on('click', function () {
// display "in progress" message or spinner here
searchDocumentsInGroups(myDocumentArray, groupSize).then(function () {
// display "complete" message or hide spinner here
});
});
});
您还需要Array.prototype.reduce的Polyfill,因为.reduce依赖于上面的版本,而较旧的浏览器(ECMAScript5之前的版本)则没有。
if ( 'function' !== typeof Array.prototype.reduce ) {
Array.prototype.reduce = function( callback /*, initialValue*/ ) {
'use strict';
if ( null === this || 'undefined' === typeof this ) {
throw new TypeError(
'Array.prototype.reduce called on null or undefined' );
}
if ( 'function' !== typeof callback ) {
throw new TypeError( callback + ' is not a function' );
}
var t = Object( this ), len = t.length >>> 0, k = 0, value;
if ( arguments.length >= 2 ) {
value = arguments[1];
} else {
while ( k < len && ! k in t ) k++;
if ( k >= len )
throw new TypeError('Reduce of empty array with no initial value');
value = t[ k++ ];
}
for ( ; k < len ; k++ ) {
if ( k in t ) {
value = callback( value, t[k], k, t );
}
}
return value;
};
}
全部未经测试,但我最近在这里回答了类似的问题,并带有小提琴的链接。
事实证明,直到jQuery-1.8为止,使用一个参数调用$.then(successFunction, successFunction)
$.then()
等效于调用$.then(successFunction, successFunction)
。 自从我使用jQuery-1.7.1以来,被拒绝的promise仍然会调用递归。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.