首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JavaScript工作队列

JavaScript工作队列
EN

Stack Overflow用户
提问于 2016-01-17 09:37:53
回答 2查看 1K关注 0票数 5

我已经创建了这个对象,它包含一个数组,它充当工作队列。

它的工作方式如下:

代码语言:javascript
复制
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){});

在这种情况下,它可以工作,在调用提交之前,我可以提交多个任务。

但是如果是这样的话:

代码语言:javascript
复制
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(),将addcommit封装在一起,但仍然无法保证,因为addWorkAndCommit()在某种意义上不可能是“原子的”,因为它们涉及异步调用。因此,即使是两次对addWorkAndCommit()的调用都可能失败。(我不知道如何用“原子”来描述它,因为JavaScript是单线程的,但出现了这个问题)。

我能做什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-17 10:09:10

问题是存在一个commit(),但没有事务的概念,所以不能显式地让两个独立的事务并行运行。据我所知,Javascript Workqueue是远程队列的代理,对add()commit()的调用直接映射到具有类似接口而没有事务的远程过程调用。我还了解到,如果第二个add()实际上发生在第一个commit()之后,您不会在意,您只想编写两个简单的后续addWorkAndCommit()语句,而不同步客户机代码中的底层调用。

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

票数 3
EN

Stack Overflow用户

发布于 2016-01-17 15:09:29

采用Benjamin Gruenbaum关于使用处置器模式的建议,下面是作为Workqueue.instance()适配器方法编写的一种模式:

代码语言:javascript
复制
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();
    });
}

现在你可以写:

代码语言:javascript
复制
// 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()

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34836955

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档