Nodejs中的并发请求处理

时间:2016-05-25 09:39:12

标签: node.js concurrency

我遇到了并发请求问题,它修改了db。

我在做什么。 一个请求获取user-1的数据,然后计算用户1的数据,修改记录中的field-1,并保存。

下一个请求获取user-1的数据,然后计算用户1的数据,修改记录中的field-1,并保存。

两个请求同时运行。所以最后一个请求更新了错误的数据。



function calculate() {
  var needUpdate = false;
  user = new UserLib(user_id);
  var old_config = user.config;
  if (old_config[req.id]) {
    old_config[req.id].value = 0;
    needUpdate = true;
  }
  if (req.delete == void(0) || req.delete == false) {
    delete req.delete;
    old_config[req.id].value = old_config[req.id].value + 1;
    needUpdate = true;
  }
  if (needUpdate) {
    return user.save();
  }
  return true;
}




enter image description here

我们同时收到两个请求。



  var express = require('express');
var app = express();

app.get('/update', function(req, res) {

  res.writeHead(200, {
    'Content-Type': 'text/html'
  });


  calculate(req);

  function calculate(req) {

    var needUpdate = false;

    user = new UserLib(user_id);
    var old_config = user.config;

    if (old_config[req.id]) {
      old_config[req.id].value = 0;
      needUpdate = true;
    }

    if (req.delete == void(0) || req.delete == false) {
      delete req.delete;
      old_config[req.id].value = old_config[req.id].value + 1;
      needUpdate = true;
    }

    if (needUpdate) {
      user.save();
    }
  }

  res.end('Done');
});
first reuest with following parameter {
  user_id: 1,
  id: 1,
  value: 5,
  delete: false
}

Anothere request with follwing parmter {
  user_id: 1,
  id: 1,
  delete: true
}




1 个答案:

答案 0 :(得分:1)

如果您想同时对每个请求进行操作,我建议您使用Bluebird.map来处理每个请求,并发性和最终结果。

例如:

let users = ['foo', 'bar']; //fetching users you want

Bluebird.map(users, (user) => {
   return user.calculate()
   .then((res) => res.shouldUpdate ? user.save() : Promise.resolve())
}, {concurrency: 2})
.then((results) => {
  //results is an array with both resolved promises from below
})

您可能还对可以计算的Bluebird.join感兴趣,并将结果数据加入到多个承诺中。

您在同一承诺中两次获取同一用户的第二个示例:

//both are promises
Bluebird.all([fetchUser1, fetchUser2])
.spread(function(user1, user2) {
   //check if should update
   return user1.delete !== user2.delete ? user.delete() : null
})
.then(() => {})

Bluebird.spread documentation