使Meteor.methods同步和异步

时间:2014-01-20 05:58:22

标签: javascript multithreading node.js asynchronous meteor

有时我需要将Meteor.call writeMeLater排队并同步执行(阻止来自同一客户端的writeMeLater的其他调用)。

其他时候,应尽快执行对writeMeLater的调用,而不排队当前排队的所有呼叫。

如果this.unblock()参数为true,则下面是我使用async的尝试。案例1和2工作正常。但是在案例3中,async=true的来电正在排在async=false的来电之后!我们怎样才能使用async=true来跳过队列?这类似于来自第二个客户端的呼叫在第一个客户端的呼叫

之后没有排队的情况

所有Meteor.call()均来自客户

案例1(正确同步):

Meteor.call('writeMeLater', 's', false)
Meteor.call('writeMeLater', 's', false)
Meteor.call('writeMeLater', 's', false)

案例2(正确异步):

Meteor.call('writeMeLater', 'a', true)
Meteor.call('writeMeLater', 'a', true)
Meteor.call('writeMeLater', 'a', true)

案例3(不是理想的行为)

Meteor.call('writeMeLater', 's', false)
Meteor.call('writeMeLater', 's', false)
Meteor.call('writeMeLater', 's', false)

Meteor.call('writeMeLater', 'a', true)
Meteor.call('writeMeLater', 'a', true)
Meteor.call('writeMeLater', 'a', true)

服务器/ main.js

writeMeLater = function(data, callback) {
    console.log('writeMeLater: ', data)

    // simulate taking 3 second to complete
    Meteor.setTimeout(function() {
        Logs.insert({data: data, timestamp: new Date().getTime()})
        console.log('Log.insert: ', data)
        callback(null, 'done')
    }, 3 * 1000)
}



writeMeLaterSync = Meteor._wrapAsync(writeMeLater)



Meteor.methods({

    writeMeLater: function(data, async) {
        if(async)
            this.unblock()

        writeMeLaterSync(data)
    }

})

1 个答案:

答案 0 :(得分:2)

我的第一个想法是,为什么不实际创建一个队列?而不是依赖JavaScript事件循环作为你的队列。然后将文档插入该队列,如:

WritesQueue = new Meteor.Collection("WritesQueue");
WritesQueue.insert({data: 'a', prioritize: true, inserted: new Date()});

也许每次插入高优先级写入时,触发Meteor.call("write")处理队列,优先(非异步)写入:

Meteor.methods({
  write: function () {
    WritesQueue.find({prioritize: true}, {sort: {inserted: 1}})
    .forEach(function (doc) {
      console.log(doc.data);
      WritesQueue.remove(doc._id);
    });
    WritesQueue.find({prioritize: false}, {sort: {inserted: 1}})
    .forEach(function (doc) {
      console.log(doc.data);
      WritesQueue.remove(doc._id);
    });
  }
});

或者,如果您希望每次插入高优先级或低优先级写入时都处理队列,请随时调用write方法或将insert放在write方法中本身。这解决了跳转到线头的问题,尽管每个客户端仍然会同步处理写入。

至于尝试为单个客户端实现并行处理,@imslavko(在上面的问题的评论中)是正确的,因为实现此目的的一种方法是客户端建立多个DDP连接。有一种相对简单的,尽管是黑客和非流星的方式:

安装Iron Router并在服务器代码中定义服务器端路由:

Router.map(function () {
  this.route('writeMeLater', {
    where: 'server',
    action: function () {
      Meteor.call('writeMeLater',
        this.request.query.data, this.request.query.async);
    }
  });
});

上面的this.request.query是一个带有键值对的对象,您随请求一起提交。例如:

HTTP.post("http://yoursite.com/writeMeLater",
  {params: {data: 'a', async: true}});

就服务器所知,此请求来自新客户端,因此将在新的光纤(即线程)中处理。如果writeMeLater方法知道不等待,则它的许多实例可以同时开始运行。现在问题变得依旧保持请求,如果对您来说服务器上的执行顺序与客户端上的执行顺序一样重要,因为HTTP POST请求可能不一定以与它们相同的顺序到达服务器。发送。但是也有各种方法可以处理它(分批发送它们,或者包括一个计数器,如果它检测到一个不按顺序的请求,让服务器等待几秒钟。)。