JavaScript工作队列

hug*_*gie 5 javascript promise bluebird

我创建了这个包含数组的对象,该数组用作工作队列.

它有点像这样:

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){});
Run Code Online (Sandbox Code Playgroud)

它适用于这种情况,我可以在调用提交之前提交多个任务.

但是,如果它是这样的:

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){});
Run Code Online (Sandbox Code Playgroud)

可能会出现问题,因为如果第二次提交后调用了第一次提交(已经添加了两个工作/任务),则第一个提交处理程序需要一个结果,但它们都会转到第二个提交处理程序.

该任务涉及Web SQL数据库读取,也可能涉及网络访问.所以它基本上是一个复杂的过程,因此可能会出现上述问题.如果只有我可以有一个addWorkAndCommit()实现包装addcommit一起,但仍然没有保证,addWorkAndCommit()因为它们在某种意义上不能是"原子",因为它们涉及异步调用.所以即使两次通话都addWorkAndCommit()可能失败.(我不知道如何用"原子"来描述它,因为JavaScript是单线程的,但是这个问题就出现了).

我能做什么?

lex*_*x82 3

问题是存在commit()但没有事务的概念,因此您不能显式地让两个独立的事务并行运行。根据我的理解,JavascriptWorkqueue是远程队列的代理,调用add()commit()直接映射到某种具有类似接口但没有事务的远程过程调用。我还理解,您不会关心第二个是否add()实际发生在第一个之后commit(),您只想编写两个简单的后续addWorkAndCommit()语句,而不同步客户端代码中的底层调用。

您可以做的是围绕本地编写一个包装器Workqueue(如果是您的代码,则直接更改它),以便队列的每次更新都会创建一个新事务,并且 acommit()始终引用一个这样的事务。然后,包装器会延迟新的更新,直到提交(或回滚)所有先前的事务。