2016-05-25 125 views
1

我有一個併發請求問題,它會修改db。Nodejs中的併發請求處理

我在做什麼。 一個請求獲取用戶1的數據,然後計算用戶1修改的記錄中的字段1的數據,然後保存。

下一次請求獲取用戶1的數據,然後計算user-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 
 
}

+0

是您使用的庫來控制流動? Promises或[async](https://github.com/caolan/async)? – soyuka

+0

我們正在使用藍鳥 –

+0

其實這是我認爲無法通過promisification處理的事情。如果你有任何解決方案,這將是欣賞。 –

回答

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

+0

其實功能是根據以前的狀態更新用戶的數據。假設所有事情都已經promisified,先取得然後更新然後返回。但要指出的是,這兩個服務器請求都是獨立的,與promisification無關。 –

+0

我不明白你的請求不能以承諾爲基礎。 'fetchUser1'不一定是一個承諾,它可以是你的舊用戶。其中'fetchUser2'是請求。 – soyuka