2014-12-09 14 views
5

Trong Node.js, tôi có nên sử dụng các lỗi để kiểm soát luồng không hoặc tôi có nên sử dụng chúng giống như ngoại lệ không?Thực tiễn tốt nhất của NodeJS: Lỗi kiểm soát luồng?

Tôi đang viết bộ điều khiển xác thực và một số kiểm tra đơn vị trong Sails.js và hiện tại, phương thức đăng ký của tôi kiểm tra xem người dùng có cùng tên người dùng đó có tồn tại hay không. Nếu người dùng đã tồn tại với tên người dùng, phương pháp mô hình của tôi gọi đối số gọi lại nó với một đối tượng Lỗi mới, như vậy:

mẫu:

exists: function (options, cb) { 
    User.findOne({ 
     where: { username: typeof options === 'Object' && options.username ? options.username : options }, 
    }).exec(function (err, user) { 
     if (err) return cb(err); 
     if (user) return cb(new Error("A user with that username already exists.")); 
     cb(null, !!user); 
    }); 
}, 

Bộ điều khiển:

User.exists(req.body.user.username, function (err, exists) { 
    if (err) { 
    console.log("error: ", err); 
    return res.status(409).json({ 
     message: err 
    });  
    } 

    User.create(req.user).then(function (data) { 
    res.status(201).json({ 
     user: data 
    }); 
    }); 
}); 

là tốt nhất này thực hành? Tôi không chắc liệu quy ước nút có ưu tiên lỗi cho các trường hợp ngoại lệ hay kiểm soát luồng không. Tôi nghĩ tôi nên viết lại điều này, nhưng tôi muốn biết các công ước trước khi tôi làm như vậy. Tôi nghĩ rằng tôi đã nhìn thấy một số ví dụ bằng văn bản theo cách này trong Sails. Cảm ơn!

+0

Một cách đơn giản hơn nhiều là cờ 'cái username' như là duy nhất trong lược đồ mô hình và chỉ cần sử dụng Lỗi Mongoose trả về trong bộ điều khiển 'User.create()' của bạn để đáp ứng với 409. Đây là một cách tiếp cận lạc quan hơn vì nếu người dùng không tồn tại và yêu cầu hợp lệ của nó, bạn không nhấn DB hai lần vì không có lý do . – srquinn

+0

@jibsales Điều đó có ý nghĩa - nhưng sau đó, điều gì sẽ xảy ra nếu có một lỗi khác có thể đòi hỏi một phản ứng 500?Trong các ngôn ngữ như C#, có nhiều loại ngoại lệ khác nhau và bạn có thể kiểm tra loại đó. Tôi biết rằng tôi có thể làm một cái gì đó như thế trong Node nếu tôi muốn, nhưng đó là thực tế phổ biến? Quyết định tôi đưa ra bây giờ sẽ ảnh hưởng đến cách tôi xây dựng phần còn lại của ứng dụng. Dựa trên nhận xét của bạn, có vẻ như Node sử dụng lỗi để kiểm soát luồng thay vì các tình huống đặc biệt. –

+0

Xem câu trả lời của tôi bên dưới – srquinn

Trả lời

2

Câu trả lời trên là tốt cho Express, nhưng trong bộ điều khiển Sails bạn không nên gọi next; thực hành tốt nhất là luôn trả lời câu trả lời. Trong hầu hết các ví dụ mã Sails bạn thậm chí sẽ không nhìn thấy next như một đối số cho một chức năng hành động điều khiển. Cũng lưu ý rằng Sails đi kèm với một số default response methods xây dựng ngay vào đối tượng res, chẳng hạn như res.serverErrorres.badRequest, cũng như res.negotiate mà sẽ cố gắng để định tuyến lỗi để xử lý thích hợp cho bạn dựa trên các mã trạng thái. Vì vậy, ví dụ bạn có thể được tinh chỉnh như:

mẫu:

exists: function (options, cb) { 
    User.findOne({ 
     where: { username: typeof options === 'Object' && options.username ? options.username : options }, 
    }).exec(function (err, user) { 
     // res.negotiate will default to a 500 server error 
     if (err) return cb(err); 
     // res.negotiate will just output the status code and error object 
     // as JSON for codes between 400 and 500, unless you 
     // provide a custom view as api/responses/badRequest.ejs 
     if (user) return cb({ 
      status: 409, 
      message: "A user with that username already exists." 
     }); 
     cb(null, !!user); 
    }); 
}, 

Bộ điều khiển:

User.exists(req.body.user.username, function (err, exists) { 
    // Let Sails handle those errors for you 
    if (err) {return res.negotiate(err);} 

    User.create(req.user).then(function (data) { 
    res.status(201).json({ 
     user: data 
    }); 
    }); 
}); 
+1

Đánh dấu câu trả lời này là chính xác - trong khi câu trả lời khác là tốt, đây là Sails cụ thể. Đối với các bản ghi, tôi đã kết thúc làm một cái gì đó tương tự, nhưng tôi tạo ra các loại lỗi của riêng tôi bằng cách mở rộng lỗi, và tôi đang kiểm tra các loại bằng cách sử dụng lời hứa Bluebird. –

2

Node (hoặc Javascript thực sự) có thể ném lỗi trên ngoại lệ bằng cách sử dụng các từ khóa throw:

if (something_went_wrong) { 
    throw new Error('Doh!'); 
} 

Bạn cũng có thể thêm các thông số bổ sung cho các đối tượng Lỗi mặc định để đem lại ý nghĩa ngữ nghĩa hơn đối với lỗi của bạn trong chương trình của bạn . Với điều đó nói rằng, bạn sẽ không muốn ném một lỗi trong xử lý tuyến đường của bạn bởi vì điều này sẽ sụp đổ quá trình và máy chủ của bạn.

Khi sử dụng trình xử lý tuyến đường trong Sails (hoặc thể hiện thực sự), bạn chắc chắn nhất nên kiểm tra loại lỗi và trả lời khách hàng tương ứng.

// -- Route handler 
app.get('/something', function (req, res, next) { 

    DB.create({ username: 'user' }, function (err, docs) { 

    if (err) { 

     // This checks to see if we have a unique error from MongoDB 
     // and send the appropriate response to the client 
     if (err.code === 11000 || error.code === 11001) { 
     return res.send(409); // or return res.json(409, {message: "User exists"}); 
     } 

     // Any other error type is assumed to be an internal error so we pass it 
     // down the chain to the error handler middleware 
     return next(err); 

    } 

    // This is a client error, not an internal error so we respond to the client 
    // with the appropriate client error type 
    if (docs.length === 0) return res.send(404); 

    if (user.notAuthorized) return res.send(403); 

    res.send('All Good'); 

    }); 

}); 

Chú ý rằng trong trường hợp đó DB đáp ứng với một lỗi nội bộ, chúng tôi vượt qua để next() chức năng mà được nhặt bằng cách xử lý lỗi middleware xuống chuỗi. Bất kỳ phần mềm trung gian nào có một mảng 4 được định nghĩa là phần mềm trung gian xử lý lỗi. Sails có thể có một số trình xử lý lỗi mặc định, nhưng bạn cũng có thể ghi đè lên nó - bạn sẽ cần phải kiểm tra các tài liệu thích hợp cho thông tin này vì tôi thích điều khiển tôi có được bằng cách sử dụng Express một mình.

+0

Tôi hiểu. Vì vậy, trong trường hợp này, tôi có thể sử dụng lỗi để kiểm soát luồng, nhưng tôi cần kiểm tra mã lỗi hoặc loại hoặc tên - điều đó có nghĩa là tôi phải tìm ra loại lỗi Mongo hoặc Sails có thể bị ném. Tôi nghĩ tôi đang tiến bộ trong nhiệm vụ tìm kiếm này. –

+0

@ jedd.ahyoung Kiểm soát lỗi cho luồng theo nghĩa là các giá trị 'err' có nghĩa là đã xảy ra lỗi. Có hay không * bạn * sử dụng nó để kiểm soát luồng là một vấn đề khác. Cũng nên xem xét rằng các thư viện khuyến khích làm cho các quy ước Node biến mất theo ý nghĩa của các ngữ nghĩa hứa hẹn bình thường. –

+0

@DaveNewton Thật vậy. Cánh buồm bao gồm [Bluebird] (https://www.npmjs.org/package/bluebird) theo mặc định và tôi đã suy nghĩ về việc sử dụng nó, thực sự, vì tôi thực sự thích mẫu lời hứa. Tuy nhiên, Bluebird cung cấp phương thức 'catch()' cho các lỗi của nó, mà (mặc dù tuyệt vời) vẫn có nghĩa là tôi phải kiểm tra các tên và kiểu lỗi. –

Các vấn đề liên quan