下面有什么比赛条件吗?

我在我的快递服务器中有下面的代码(为了简洁起见,请把它剪下来)。 我有一个共同的对象,我正在添加/修改/阅读三个不同的宁静的终点。 由于nodejs中的所有http请求都是asynchronous的,所以我可以同时获得请求和请求。 所以,虽然PUT发生,但让我们说状态更新,我的GET可以得到一个稍微陈旧的回应?

根据我的理解,我的testing显示这里没有竞争条件。 因为更新results对象是一个同步操作,所有的asynchronous操作应该等待它。 有人可以帮助更好地解释这是否正确?

  var obj = {}; const exec = require('child_process').exec; app.post('/foo', (req, res) => { var result = {}; result.id = generateSomeRandomId(); result.failed = 0; result.status = 'running' //execute some command and update result const child = exec('some command'); child.stdout.on('data', (data) => { //some logic }); child.stderr.on('data', (data) => { result.failed = result.failed + 1; }); child.on('close', (code, signal) => { if (signal !== null && signal !== undefined) { result.status = 'cancelled'; } else { result.status = 'completed'; result.runtime = calculateRunTime(); } }); result.pid = child.pid; obj[result.id] = result; res.send(result); } app.put('/foo/:id', (req, res) => { var result = obj[req.params.id]; if (result.status === 'running' && result.pid !== undefined) { kill(result.pid, 'SIGKILL'); result.status = 'cancelled'; result.runtime = calculateRunTime(); } res.send(result); } app.get('/foo/:id', (req, res) => { var result = obj[req.params.id]; res.send(result); } 

你没有任何我称之为“竞赛条件”的东西; 这里有一个不确定的因素,但实际上这不太可能是重要的。

它看起来像你的post开始一个进程,并返回ID,你的put取消进程,你的get返回进程的当前状态。 从这我收集,你将永远不能get直到你的post完成并提供该ID。

如果你在你的execasynchronous监听器完成之前做了一个接收和返回的get调用,你将得到任何最后的进行中的状态 – 我假设这是devise。 所以这里唯一可能的冲突是如果你打了一个电话来停止你的过程。

当你和你的结果对象进行交互时,你的putget都是同步的,所以无论先接收哪一个,都是先完成的。 您可以忽略进程取消请求,因为它不修改结果对象。 不能保证他们会以客户发送的相同顺序收到,这可能会或可能不会成为您场景中的实际问题。

相信 (尽pipe我的内存可能是错误的),如果你使用cluster来处理不同进程中的请求,你将无法通过一个共享对象传递数据,所以任何增加了这种可能性的复杂性已经排除。

所以,networking性能和可靠性的差异是你唯一真正的通配符。 服务器将按照它们进来的顺序处理请求,并给你预期的结果。 如果你只有一个客户端,你可以等到你之前的请求发送下一个请求的响应,这可能会让你的性能变得不可接受,但或多或​​less的防弹。 否则,只需发送您的请求,不用担心,只要让您的应用程序足够健壮即可识别并处理第二个取消请求,即使您已经取消了该过程。

这只是一个想法,但也许一个承诺可能会在这里有所帮助:

 var obj = {}; const exec = require('child_process').exec; app.post('/foo', (req, res) => { var result = {}; result.id = generateSomeRandomId(); result.status = 'running'; const child = exec('some command'); child.stdout.on('data', (data) => { //some logic }); result.promise = new Promise(resolve => { child.stderr.on('data', (data) => { result.failed = result.failed + 1; resolve(false); }); child.on('close', (code, signal) => { // ... resolve(true); }); }); result.pid = child.pid; obj[result.id] = result; res.send(result); } app.get('/foo/:id', (req, res) => { var result = obj[req.params.id]; if(result.status === 'running') { result.promise.then(() => res.send(result)); } else { res.send(result); } } 

在这种情况下,只有当child由错误或“closures”事件完成时,GET才会作出响应。