2015-09-30 22 views
1

我希望得到一些有關以下問題的幫助。我正在編寫我的bsc論文,這部分代碼將負責註冊用戶。 (我實際上是nodejs的新手)。我也使用快遞和貓鼬。在NodeJS中發送不同的POST響應

我想處理請求數據,並檢查一些錯誤,首先我想檢查是否所有字段都存在,其次如果有人已經註冊了此電子郵件地址。

根據錯誤(或成功),我想發送不同的答覆。如果缺少一個字段,那麼400錯誤的請求(如果用戶存在),然後是409衝突,如果一切正常,則爲200 OK。但我只想做回調,如果沒有錯誤,但我有點卡在這裏...我得到的錯誤發送後無法設置標頭,這實際上很明顯,因爲JS繼續處理代碼即使設置了響應。

app.post('/register', function (req, res) { 
    var user = new User(req.body); 

    checkErrors(req, res, user, registerUser); 
}); 

var registerUser = function(req, res, user){ 
    user.save(function(err, user){ 
     if (err) return console.log(err); 
    }); 
    res.sendStatus(200); 
}; 

var checkErrors = function(req, res, user, callback){ 
    var properties = [ 'firstName', 'lastName', 'email', 'password', 'dateOfBirth' ]; 

    for(var i = 0; i < properties.length; i++){ 
     if(!req.body.hasOwnProperty(properties[i])){ 
      res.status(400).send('field ' + properties[i] + ' not found'); 
     } 
    } 

    var criteria = { 
     email: req.body.email 
    }; 
    User.find(criteria).exec(function(err, user){ 
     if(user.length > 0){ 
      res.status(409).send('user already exists'); 
     } 
    }); 
    callback(req, res, user); 
}; 

回答

0

我認爲這個問題是在checkErrorsfor循環。由於您在循環中調用res.status(400).send(),最終可能會多次調用它,這會在第一次調用後觸發錯誤,因爲響應已被髮送回客戶端。

在循環內部,您可以將缺失的字段添加到數組中,然後檢查數組的長度以查看是否應使用400作出響應或繼續。這樣,您只會撥打res.status(400).send()一次。

例如:

... 
var missingFields = []; 
for(var i = 0; i < properties.length; i++){ 
    if(!req.body.hasOwnProperty(properties[i])){ 
     missingFields.push(properties[i]); 
    } 
} 
if(missingFields.length > 0) { 
    return res.status(400).send({"missingFields" : missingFields}); 
} 
... 

一般情況下,我建議你在每個res.send()電話前加上return,以確保沒有其他意外呼籲以後。

的一個例子是:

User.find(criteria).exec(function(err, user){ 
    // We put return here in case you later add conditionals that are not 
    // mutually exclusive, since execution will continue past the 
    // res.status() call without return 
    if(user.length > 0){ 
     return res.status(409).send('user already exists'); 
    } 
    // Note that we also put this function call within the block of the 
    // User.find() callback, since it should not execute until 
    // User.find() completes and we can check for existing users. 
    return callback(req, res, user); 
}); 

您可能注意到我感動callback(req, res, user)。如果我們將callback(req, res, user)留在User.find()回調的主體之外,則有可能在User.find()完成之前執行。這是使用Node.js進行異步編程的一個小技巧。當任務完成時,回調函數會發出信號,所以如果您不包裝要在回調中順序執行的操作,則可以在與源代碼無關的情況下執行「無序」操作。

在附註中,在功能registerUser中,如果user.save發生故障,則客戶端永遠不會知道,因爲該功能會爲任何請求發送200狀態碼。發生這種情況的原因與我上面提到的相同:因爲res.sendStatus(200)未包含在user.save回調函數中,所以它可能在保存操作完成之前運行。如果在保存過程中發生錯誤,您應該告訴客戶端,可能使用500狀態碼。例如:

var registerUser = function(req, res, user){ 
    user.save(function(err, user){ 
     if (err) { 
      console.error(err); 
      return res.status(500).send(err); 
     } 
     return res.sendStatus(201); 
    }); 
}; 
+0

非常感謝,這非常有用! – Martin

0

您對registerUser()呼叫在路線後界定,將undefined,因爲它不是一個懸掛功能。
您在關閉時使用scope是不正確的。對於您的特定錯誤,這是因爲您在循環中運行res.send(),因爲它只應該在每個請求中被調用一次(因此已經發送了已發送的頭域a.k.a.響應)。您也應該在致電res.send()後直接從功能返回。