有时我需要将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)
}
})
答案 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请求可能不一定以与它们相同的顺序到达服务器。发送。但是也有各种方法可以处理它(分批发送它们,或者包括一个计数器,如果它检测到一个不按顺序的请求,让服务器等待几秒钟。)。