Mặc dù mã của bạn không xử lý được một số trường hợp lỗi và sử dụng find
sai chức năng, dòng chảy chung là điển hình cho công việc bạn muốn làm.
- Nếu có lỗi khác với lỗi trùng lặp, thì lệnh gọi lại sẽ không được gọi, điều này có thể gây ra sự cố xuống dòng trong ứng dụng NodeJs của bạn
- sử dụng
findOne
thay vìfind
vì sẽ chỉ có một kết quả cho biết khóa là duy nhất. Nếu không, nó sẽ trả về một mảng. - Nếu cuộc gọi lại của bạn dự kiến là lỗi
error
truyền thống là đối số đầu tiên, bạn có thể chuyển trực tiếp lệnh gọi lại đếnfindOne
chức năng hơn là giới thiệu một chức năng ẩn danh. - Bạn cũng có thể muốn xem
findOneAndUpdate
cuối cùng, tùy thuộc vào lược đồ và logic cuối cùng của bạn sẽ là gì.
Như đã đề cập, bạn có thể sử dụng findOneAndUpdate
, nhưng với chi phí bổ sung.
function save(id, title, callback) {
Value.findOneAndUpdate(
{id: id, title: title}, /* query */
{id: id, title: title}, /* update */
{ upsert: true}, /* create if it doesn't exist */
callback);
}
Tất nhiên vẫn có một lệnh gọi lại, nhưng nó sẽ ghi lại dữ liệu nếu tìm thấy bản sao. Đó có phải là một vấn đề thực sự phụ thuộc vào các trường hợp sử dụng hay không.
Tôi đã làm sạch một chút mã của bạn ... nhưng nó thực sự khá đơn giản và lệnh gọi lại phải rõ ràng. callback
hàm luôn nhận được tài liệu mới được lưu hoặc tài liệu đã được so khớp dưới dạng bản sao. Đó là trách nhiệm của hàm gọi saveNewValue
để kiểm tra lỗi và xử lý đúng cách. Bạn sẽ thấy cách tôi cũng đã đảm bảo rằng lệnh gọi lại được gọi bất kể loại lỗi nào và luôn được gọi với kết quả theo một cách nhất quán.
function saveNewValue(id, title, callback) {
if (!callback) { throw new Error("callback required"); }
var thisValue = new models.Value({
id:id,
title:title //this is a unique value
});
thisValue.save(function(err, product) {
if (err) {
if (err.code === 11000) { //error for dupes
return models.Value.findOne({title:title}, callback);
}
}
callback(err, product);
});
}
Ngoài ra, bạn có thể sử dụng lời hứa họa tiết. Ví dụ này đang sử dụng when.js .
var when = require('when');
function saveNewValue(id, title) {
var deferred = when.defer();
var thisValue = new models.Value({
id:id,
title:title //this is a unique value
});
thisValue.save(function(err, product) {
if (err) {
if (err.code === 11000) { //error for dupes
return models.Value.findOne({title:title}, function(err, val) {
if (err) {
return deferred.reject(err);
}
return deferred.resolve(val);
});
}
return deferred.reject(err);
}
return deferred.resolve(product);
});
return deferred.promise;
}
saveNewValue('123', 'my title').then(function(doc) {
// success
}, function(err) {
// failure
});