我已经创建了这个对象,它包含一个数组,它充当工作队列。
它的工作方式如下:
var work1 = new Work();
var work2 = new Work();
var queue = Workqueue.instance();
queue.add(work1) // Bluebird promise.
.then(function addWork2() {
return queue.add(work2);
})
.then(function toCommit() {
return queue.commit();
})
.then(function done(results) {
// obtain results here.
})
.catch(function(err){});在这种情况下,它可以工作,在调用提交之前,我可以提交多个任务。
但是如果是这样的话:
var work1 = new Work();
var work2 = new Work();
var queue = Workqueue.instance();
queue.add(work1)
.then(function toCommit1() {
return queue.commit();
})
.then(function done1(result1) {
// obtain result1 here.
})
.catch(function(err){});
queue.add(work2)
.then(function toCommit2() {
return queue.commit();
})
.then(function done2(result2) {
// obtain result2 here.
})
.catch(function(err){});可能出了问题,因为如果第一次提交是在第二次提交之后调用的(已经添加了两个工作/任务),第一个提交处理程序希望得到一个结果,但它们都会转到第二个提交处理程序。
该任务涉及Web SQL数据库的读取,也可能涉及网络访问。因此,这基本上是一个复杂的过程,因此上述问题可能会浮出水面。如果我能够实现一个addWorkAndCommit(),将add和commit封装在一起,但仍然无法保证,因为addWorkAndCommit()在某种意义上不可能是“原子的”,因为它们涉及异步调用。因此,即使是两次对addWorkAndCommit()的调用都可能失败。(我不知道如何用“原子”来描述它,因为JavaScript是单线程的,但出现了这个问题)。
我能做什么?
发布于 2016-01-17 10:09:10
问题是存在一个commit(),但没有事务的概念,所以不能显式地让两个独立的事务并行运行。据我所知,Javascript Workqueue是远程队列的代理,对add()和commit()的调用直接映射到具有类似接口而没有事务的远程过程调用。我还了解到,如果第二个add()实际上发生在第一个commit()之后,您不会在意,您只想编写两个简单的后续addWorkAndCommit()语句,而不同步客户机代码中的底层调用。
您可以做的是围绕本地Workqueue编写一个包装器(或者直接修改它,如果它是您的代码),这样队列的每次更新都会创建一个新的事务,并且commit()总是引用一个这样的事务。然后包装器会延迟新的更新,直到提交(或回滚)所有以前的事务。
发布于 2016-01-17 15:09:29
采用Benjamin Gruenbaum关于使用处置器模式的建议,下面是作为Workqueue.instance()适配器方法编写的一种模式:
Workqueue.transaction = function (work) { // `work` is a function
var queue = this.instance();
return Promise.resolve(work(queue)) // `Promise.resolve()` avoids an error if `work()` doesn't return a promise.
.then(function() {
return queue.commit();
});
}现在你可以写:
// if the order mattters,
// then add promises sequentially.
Workqueue.transaction(function(queue) {
var work1 = new Work();
var work2 = new Work();
return queue.add(work1)
.then(function() {
return queue.add(work2);
});
});
// if the order doesn't mattter,
// add promises in parallel.
Workqueue.transaction(function(queue) {
var work1 = new Work();
var work2 = new Work();
var promise1 = queue.add(work1);
var promise2 = queue.add(work2);
return Promise.all(promise1, promise2);
});
// you can even pass `queue` around
Workqueue.transaction(function(queue) {
var work1 = new Work();
var promise1 = queue.add(work1);
var promise2 = myCleverObject.doLotsOfAsyncStuff(queue);
return Promise.all(promise1, promise2);
});实际上,应该包括这样的错误处理程序- Workqueue.transaction(function() {...}).catch(errorHandler);。
无论您编写什么,您所需要做的就是确保回调函数返回一个包含所有组件异步(组件承诺)的承诺。当聚合承诺解决时,处置者将确保事务已提交。
和所有的处置者一样,这个人不会做任何没有它你不能做的事情。然而,它:
.transaction()方法来提醒您正在做的事情,Workqueue.instance()约束为一次提交,强制执行单个事务的概念。如果出于任何原因,您需要在同一个队列上执行两个或多个提交(为什么?),则始终可以恢复直接调用Workqueue.instance()。
https://stackoverflow.com/questions/34836955
复制相似问题