使用jQuery.Queue()对ajax请求进行排队
我第一次使用jQuery.queue(),但还没有完全掌握它。 有人能指出我做错了什么吗 在firebug中,我仍然看到我的POST请求同时启动——因此我想知道我是否在错误的位置调用了dequeue() 还有-如何获取队列长度 我需要对这些请求排队的原因是,它会在单击按钮时被触发。用户可以快速连续单击多个按钮 试图删除我的代码的基本结构:使用jQuery.Queue()对ajax请求进行排队,jquery,ajax,queue,Jquery,Ajax,Queue,我第一次使用jQuery.queue(),但还没有完全掌握它。 有人能指出我做错了什么吗 在firebug中,我仍然看到我的POST请求同时启动——因此我想知道我是否在错误的位置调用了dequeue() 还有-如何获取队列长度 我需要对这些请求排队的原因是,它会在单击按钮时被触发。用户可以快速连续单击多个按钮 试图删除我的代码的基本结构: $("a.button").click(function(){ $(this).doAjax(params); }); // method doAja
$("a.button").click(function(){
$(this).doAjax(params);
});
// method
doAjax:function(params){
$(document).queue("myQueueName", function(){
$.ajax({
type: 'POST',
url: 'whatever.html',
params: params,
success: function(data){
doStuff;
$(document).dequeue("myQueueName");
}
});
});
}
这里的问题是,
.ajax()
触发一个异步运行的ajax请求。这意味着,.ajax()
立即返回,无阻塞。因此,您可以对函数进行排队,但它们几乎会像您描述的那样同时启动
我认为.queue()
不是一个放置ajax请求的好地方,它更适合使用fx方法。你需要一个简单的经理
var ajaxManager = (function() {
var requests = [];
return {
addReq: function(opt) {
requests.push(opt);
},
removeReq: function(opt) {
if( $.inArray(opt, requests) > -1 )
requests.splice($.inArray(opt, requests), 1);
},
run: function() {
var self = this,
oriSuc;
if( requests.length ) {
oriSuc = requests[0].complete;
requests[0].complete = function() {
if( typeof(oriSuc) === 'function' ) oriSuc();
requests.shift();
self.run.apply(self, []);
};
$.ajax(requests[0]);
} else {
self.tid = setTimeout(function() {
self.run.apply(self, []);
}, 1000);
}
},
stop: function() {
requests = [];
clearTimeout(this.tid);
}
};
}());
这还远远不够完美,我只是想展示一下该怎么做。上面的例子可以这样使用
$(function() {
ajaxManager.run();
$("a.button").click(function(){
ajaxManager.addReq({
type: 'POST',
url: 'whatever.html',
data: params,
success: function(data){
// do stuff
}
});
});
});
我发现上面的解决方案有点复杂,而且我需要在发送请求之前修改请求(以更新新的数据令牌)
所以我把这个放在一起。资料来源:
我需要做一件类似的事情,所以我想我应该在这里发布我的解决方案
基本上我得到的是一个页面,上面列出了书架上的项目,这些项目都有不同的标准。我想一个接一个地加载书架,而不是全部加载,以便更快地将一些内容发送给用户,让他们在加载其余内容的同时可以查看这些内容
基本上,我将每个工具架的ID存储在一个JS数组中,从PHP调用它们时使用该数组
然后,我创建了一个递归函数,每次调用它时,它都会从数组中弹出第一个索引,并为弹出的id请求shelf。一旦我从$.get()
或$.post()
中得到响应,我就从回调中调用递归函数
下面是代码的详细说明:
// array of shelf IDs
var shelves = new Array(1,2,3,4);
// the recursive function
function getShelfRecursive() {
// terminate if array exhausted
if (shelves.length === 0)
return;
// pop top value
var id = shelves[0];
shelves.shift();
// ajax request
$.get('/get/shelf/' + id, function(){
// call completed - so start next request
getShelfRecursive();
});
}
// fires off the first call
getShelfRecursive();
我还必须在我现有的解决方案中这样做,我发现我可以这样做:
//A variable for making sure to wait for multiple clicks before emptying.
var waitingTimeout;
$("a.button").click(function(){
$(this).doAjax(params);
clearTimeout(waitingTimeout);
waitingTimeout = setTimeout(function(){noMoreClicks();},1000);
});
// method
doAjax:function(params){
$(document).queue("myQueueName", function(next){
$.ajax({
type: 'POST',
url: 'whatever.html',
data: params,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data){
doStuff;
next();
},
failure: function(data){
next();
},
error: function(data){
next();
}
});
});
}
function noMoreClicks(){
$(document).dequeue("myQueueName");
}
通过使用队列函数中传递的next()
回调,您可以将下一个操作出列。因此,通过将下一个放在ajax的处理程序中,可以有效地使ajax调用与浏览器和浏览器的渲染或绘制线程异步,但使它们彼此同步或序列化
var dopostqueue = $({});
function doPost(string, callback)
{
dopostqueue.queue(function()
{
$.ajax(
{
type: 'POST',
url: 'thephpfile.php',
datatype: 'json',
data: string,
success:function(result)
{
dopostqueue.dequeue();
callback(JSON.parse(result));
}
})
});
}
在这个例子中,小提琴。单击按钮一次,然后等待一秒钟。您将看到超时触发并执行单个操作。下一步,尽可能快地(或快于1秒)单击按钮,您将看到每次单击按钮时,操作都在排队,只有等待一秒钟后,操作才会进入页面并一个接一个地淡入
这样做的好处是,如果队列已经清空,那么在清空时添加到队列中的任何操作都会放在末尾,然后在时机成熟时进行处理。对于未知数量的ajax调用,我需要这样做。答案是将每一个都推入一个数组,然后使用:
$.when.apply($, arrayOfDeferreds).done(function () {
alert("All done");
});
learn.jquery.com网站:
//jQuery在一个空对象上,我们将使用它作为队列
var ajaxQueue=$({});
$.ajaxQueue=函数(ajaxOpts){
//保留原始完整功能
var oldComplete=ajaxOpts.complete;
//对ajax请求进行排队
队列(函数(下一步){
//创建一个完整的回调来调用队列中的下一个事件
ajaxOpts.complete=函数(){
//调用原始的complete,如果它在那里的话
如果(已完成){
oldComplete.apply(这个,参数);
}
//运行队列中的下一个查询
next();
};
//运行查询
$.ajax(ajaxOpts);
});
};
//获取我们要复制的每个项目
$(“#项li”)。每个(功能(idx){
//将ajax请求排队
$.ajaxQueue({
url:“/ajax\u html\u echo/”,
数据:{
html:“[”+idx+“]”+$(this.html()
},
类型:“POST”,
成功:功能(数据){
//写入#输出
$(“#输出”)。追加($(“”{
html:数据
}));
}
});
});
您可以扩展jQuery:
(function($) {
// Empty object, we are going to use this as our Queue
var ajaxQueue = $({});
$.ajaxQueue = function(ajaxOpts) {
// hold the original complete function
var oldComplete = ajaxOpts.complete;
// queue our ajax request
ajaxQueue.queue(function(next) {
// create a complete callback to fire the next event in the queue
ajaxOpts.complete = function() {
// fire the original complete if it was there
if (oldComplete) oldComplete.apply(this, arguments);
next(); // run the next query in the queue
};
// run the query
$.ajax(ajaxOpts);
});
};
})(jQuery);
然后像这样使用它:
$.ajaxQueue({
url: 'doThisFirst.php',
async: true,
success: function (data) {
//success handler
},
error: function (jqXHR,textStatus,errorThrown) {
//error Handler
}
});
$.ajaxQueue({
url: 'doThisSecond.php',
async: true,
success: function (data) {
//success handler
},
error: function (jqXHR,textStatus,errorThrown) {
//error Handler
}
});
当然,您可以使用任何其他$.ajax选项,如type、data、contentType、DataType,因为我们正在扩展$.ajax,它是jAndy答案的另一个版本,没有计时器
var ajaxManager = {
requests: [],
addReq: function(opt) {
this.requests.push(opt);
if (this.requests.length == 1) {
this.run();
}
},
removeReq: function(opt) {
if($.inArray(opt, requests) > -1)
this.requests.splice($.inArray(opt, requests), 1);
},
run: function() {
// original complete callback
oricomplete = this.requests[0].complete;
// override complete callback
var ajxmgr = this;
ajxmgr.requests[0].complete = function() {
if (typeof oricomplete === 'function')
oricomplete();
ajxmgr.requests.shift();
if (ajxmgr.requests.length > 0) {
ajxmgr.run();
}
};
$.ajax(this.requests[0]);
},
stop: function() {
this.requests = [];
},
}
使用:
$(function() {
$("a.button").click(function(){
ajaxManager.addReq({
type: 'POST',
url: 'whatever.html',
data: params,
success: function(data){
// do stuff
}
});
});
});
这是我的解决方案,我使用它为一些浏览器游戏生成一个请求队列。
如果发生任何事情,我会停止这个队列,并完成一些特殊的最后请求或清理工作
var get_array = ["first", "second", "third"];
var worker = $("<div />"); // to line up requests in queue
$.queuedAjax = function(args){ // add up requests for me
worker.queue(
function(next){
$.ajax(args).always(next);
}
);
};
$.queuedSomething = function(){ // add up something special for me
worker.queue(
function(next){
//worker.clearQueue();
//worker = $("<div />"); //cleanup for next .each
//maybe another .each
}
);
};
$.each( get_array , function( key , value ) {
$.queuedAjax({
type: 'GET',
url: '/some.php?get='+value,
dataType: 'text',
success: function(sourcecode){
if (sourcecode.match(/stop your requests, idiot!/)) {
worker.clearQueue().queue($.queuedSomething);
alert(' the server told me to stop. i stopped all but not the last ´$.queuedSomething()´ ');
}
}
});
});
$.queuedSomething();
var get_数组=[“第一”、“第二”、“第三”];
var worker=$(“”);//在队列中排列请求
$.queuedAjax=函数(args){//为我添加请求
工作队列(
功能(下一个){
$.ajax(args).always(next);
}
);
};
$.queuedSomething=function(){//为我添加一些特别的东西
工作队列(
功能(下一个){
//worker.clearQueue();
//worker=$(“”);//下一步的清理。每个
//也许是另一个,每个
}
);
};
$.each(获取数组、函数(键、值){
$.queuedAjax({
键入:“GET”,
url:'/some.php?get='+value,
数据类型:“文本”,
成功:函数(源代码){
if(sourcecode.match(/停止你的请求,傻瓜!/){
worker.clearQueue().queue($.queuedSomething);
警报('服务器告诉我停止。我停止了所有,但没有停止最后一个´$.queuedSomething()');
}
}
});
});
$.queuedSomething();
我使用这个非常简单的代码来防止ajax调用相互“超越”
var dopostqueue = $({});
function doPost(string, callback)
{
dopostqueue.queue(function()
{
$.ajax(
{
type: 'POST',
url: 'thephpfile.php',
datatype: 'json',
data: string,
success:function(result)
{
dopostqueue.dequeue();
callback(JSON.parse(result));
}
})
});
}
如果不希望队列自行处理,可以从函数中删除dequeue
,然后从另一个函数调用它
var dopostqueue = $({});
function doPost(string, callback)
{
dopostqueue.queue(function()
{
$.ajax(
{
type: 'POST',
url: 'thephpfile.php',
datatype: 'json',
data: string,
success:function(result)
{
dopostqueue.dequeue();
callback(JSON.parse(result));
}
})
});
}
dopostqueue.queue().length
/*
Job Queue Runner (works with nodejs promises): Add functions that return a promise, set the number of allowed simultaneous threads, and then run
(*) May need adaptation if used with jquery or angular promises
Usage:
var sourcesQueue = new QueueRunner('SourcesQueue');
sourcesQueue.maxThreads = 1;
childSources.forEach(function(source) {
sourcesQueue.addJob(function() {
// Job function - perform work on source
});
}
sourcesQueue.run().then(function(){
// Queue complete...
});
*/
var QueueRunner = (function () {
function QueueRunner(id) {
this.maxThreads = 1; // Number of allowed simultaneous threads
this.jobQueue = [];
this.threadCount = 0;
this.jobQueueConsumer = null;
this.jobsStarted = 0;
if(typeof(id) !== 'undefined') {
this.id = id;
}
else {
this.id = 'QueueRunner';
}
}
QueueRunner.prototype.run = function () {
var instance = this;
return new Promise(function(resolve, reject) {
instance.jobQueueConsumer = setInterval(function() {
if(instance.threadCount < instance.maxThreads && instance.jobQueue.length > 0) {
instance.threadCount++;
instance.jobsStarted++;
// Remove the next job from the queue (index zero) and run it
var job = instance.jobQueue.splice(0, 1)[0];
logger.info(instance.id + ': Start job ' + instance.jobsStarted + ' of ' + (instance.jobQueue.length + instance.jobsStarted));
job().then(function(){
instance.threadCount--;
}, function(){
instance.threadCount--;
});
}
if(instance.threadCount < 1 && instance.jobQueue.length < 1) {
clearInterval(instance.jobQueueConsumer);
logger.info(instance.id + ': All jobs done.');
resolve();
}
}, 20);
});
};
QueueRunner.prototype.addJob = function (func) {
this.jobQueue.push(func);
};
return QueueRunner;
}());
var ajaxQueueMax = 5;
self.ajaxQueue = ko.observableArray();
self.ajaxQueueRunning = ko.observable(0);
ko.computed(function () {
if (self.ajaxQueue().length > 0 && self.ajaxQueueRunning() < ajaxQueueMax) {
var next = self.ajaxQueue.shift();
self.ajaxQueueRunning(self.ajaxQueueRunning() + 1);
$.ajax(next).always(function () {
self.ajaxQueueRunning(self.ajaxQueueRunning() - 1);
});
}
});
self.widgets = ko.observableArray();
ko.computed(function () {
var mapping = {
create: function (options) {
var res = ko.mapping.fromJS(options.data);
res.count = ko.observable();
// widget enrichment.
self.ajaxQueue.push({
dataType: "json",
url: "/api/widgets/" + options.data.id + "/clicks",
success: function (data) {
res.count(data);
}
});
return res;
}
};
// Initial request for widgets
$.getJSON("/api/widgets", function (data) {
ko.mapping.fromJS(data, mapping, self.widgets);
});
});