如何让Backbone.js克隆操作等待服务器完成后再执行?
解决快速点击克隆书籍导致rowOrderNumber混乱的问题
你的问题核心是异步请求并发执行:多个克隆请求同时发起后,服务器生成rowOrderNumber时可能基于同一时刻的最大值计算,导致顺序混乱或重复。可以通过前端控制请求串行执行,让每个克隆操作等待前一个完成后再进行,具体实现有两种方式:
方式一:阻止重复点击(简单直接)
在视图中维护一个状态标志,标记当前是否有克隆操作正在进行,同时禁用按钮避免用户重复点击:
// 在视图的initialize方法中初始化状态 initialize: function() { this.isCloning = false; }, clonebook: function () { var self = this; // 如果正在克隆,直接返回 if (this.isCloning) return; this.isCloning = true; // 禁用copy按钮,视觉上提示用户 this.$el.find('.copy-btn').prop('disabled', true); this.book.clone().then((r) => { self.model.collection.add(r); }).finally(() => { // 无论请求成功或失败,都重置状态和按钮 self.isCloning = false; self.$el.find('.copy-btn').prop('disabled', false); }); },
方式二:任务队列(处理多次点击的排队需求)
如果需要支持用户多次点击,让所有克隆请求按顺序依次执行,可以用队列存储任务,逐个处理:
initialize: function() { this.cloneQueue = []; this.isCloning = false; }, clonebook: function () { var self = this; // 将克隆任务加入队列 this.cloneQueue.push(() => { return self.book.clone().then((r) => { self.model.collection.add(r); }); }); // 如果当前没有执行中的任务,启动队列处理 if (!this.isCloning) { this.processCloneQueue(); } }, processCloneQueue: function() { var self = this; // 队列空了就结束 if (this.cloneQueue.length === 0) { this.isCloning = false; this.$el.find('.copy-btn').prop('disabled', false); return; } this.isCloning = true; this.$el.find('.copy-btn').prop('disabled', true); // 取出队列第一个任务执行 const currentTask = this.cloneQueue.shift(); currentTask().then(() => { // 递归处理下一个任务 self.processCloneQueue(); }).catch((err) => { // 处理错误,不影响后续任务执行 console.error('克隆失败:', err); self.processCloneQueue(); }); },
补充:后端原子性保障(可选)
为了彻底避免并发问题,建议后端生成rowOrderNumber时使用原子操作,比如在SQL Server中用事务结合MAX函数:
BEGIN TRANSACTION; DECLARE @newOrder INT; SELECT @newOrder = ISNULL(MAX(rowOrderNumber), 0) + 1 FROM book WHERE libraryId = @targetLibraryId; INSERT INTO book (bookTitle, authorId, libraryId, rowOrderNumber) VALUES (@title, @authorId, @targetLibraryId, @newOrder); COMMIT TRANSACTION;
这样即使前端有漏网的并发请求,后端也能保证rowOrderNumber的唯一性和顺序性。
内容的提问来源于stack exchange,提问作者SkyeBoniwell
相关产品推荐
相关产品推荐

