2015-11-19 23 views
8

Tôi đang cố triển khai mô-đun cho các lỗi tùy chỉnh.Lỗi tùy chỉnh và bắt gặp của bluebird với ErrorClass dẫn đến hành vi vô ý

Nó phải có khả năng nhanh chóng một lỗi cá nhân trong phạm vi yêu cầu-tuyên bố của ứng dụng bằng môđun này:

var MyCustomError = require('custom-error')('MyCustomError'); 

này là mô-đun:

'use strict'; 

var _CACHE = {}; 

function initError(name) { 
    function CustomError(message) { 
    this.name = name; 
    this.message = message; 
    } 
    CustomError.prototype = Object.create(Error.prototype); 
    CustomError.prototype.constructor = CustomError; 
    _CACHE[name] = CustomError; 
} 

function createCustomError(name) { 
    if (!_CACHE[name]) { 
    initError(name); 
    } 
    return _CACHE[name]; 
} 

module.exports = createCustomError; 

Các yêu cầu-một-liner ở trên là làm việc cho đến nay.

Bây giờ, trong dịch vụ của tôi, tôi muốn bắt lỗi này một cách rõ ràng:

var MyCustomError = require('custom-error')('MyCustomError') 
// ... 
return fooService.bar() 
    .catch(MyCustomError, function (error) { 
     logger.warn(error); 
     throw error; 
    }) 

Nếu tôi từ chối lời hứa của fooService.bar trong thử nghiệm của tôi bằng cách ném một MyCustomError này đang làm việc tuyệt vời.

NHƯNG, điều này chỉ hoạt động vì thử nghiệm của tôi và dịch vụ đang sử dụng cùng một trường hợp của MyCustomError.

Ví dụ: nếu tôi xóa cơ chế lưu trong bộ nhớ cache trong mô-đun lỗi tùy chỉnh của mình, lệnh bắt sẽ không được truy cập/thực thi nữa, vì bluebird không hiểu rằng hai lỗi cùng loại:

function createCustomError(name) { 
    //if (!_CACHE[name]) { 
    initError(name); 
    //} 
    return _CACHE[name]; 
} 

Mã cụ thể của việc xử lý bluebird nằm trong catch_filter.js, bạn có thể xem right here.

Mặc dù cách tiếp cận không hoạt động trong ứng dụng của tôi, điều này sẽ sớm dẫn đến sự cố khi nhiều mô-đun đang sử dụng mô-đun lỗi tùy chỉnh và chia sẻ cùng một trường hợp không được cung cấp nữa.

Làm cách nào để tôi có thể thiết lập và chạy khái niệm này bằng cách không so sánh các trường hợp, nhưng chính loại lỗi ?

Chúc mừng,
Christopher

Trả lời

3

Cuối cùng tôi đã đưa ra một cách tiếp cận hơi khác nhau. Đối với những người có cùng khuynh hướng này là kết quả:

ErrorFactory

var 
    vsprintf = require("sprintf-js").vsprintf; 

function CustomErrorFactory(code, name, httpCode, message) { 

    // Bluebird catcher 
    this.predicate = function (it) { 
    return it.code === code; 
    }; 

    this.new = function (messageParameters, details) { 
    return new CustomError(messageParameters, details); 
    }; 

    this.throw = function (messageParameters, details) { 
    throw new CustomError(messageParameters, details); 
    }; 

    function CustomError(messageParameters, details) { 
    this.code = code; 
    this.name = name; 
    this.message = vsprintf(message, messageParameters); 
    this.httpCode = httpCode; 
    this.details = details || {}; 

    // Important: Do not swallow the stacktrace that lead to here. 
    // @See http://stackoverflow.com/questions/8802845/inheriting-from-the-error-object-where-is-the-message-property 
    Error.captureStackTrace(this, CustomError); 
    } 

    // CustomError must be instance of the Error-Object 
    CustomError.prototype = Object.create(Error.prototype); 
    CustomError.prototype.constructor = CustomError; 
} 

module.exports = CustomErrorFactory; 

lỗi

var 
    ErrorFactory = require("./ErrorFactory"); 

function initErrors() { 
    return { 
    Parameter: { 
     Missing: new ErrorFactory('1x100', 'ParameterMissing', 400, 'Parameter "%s" missing'), 
     Invalid: new ErrorFactory('1x200', 'ParameterInvalid', 400, 'Parameter "%s" invalid') 
     //.. 
    }, 
    Access: { 
     NotAccessible: new ErrorFactory('3x100', 'AccessNotAccessible', 403, 'Resource "%s" is not accessible for "%s"'), 
     //.. 
    }, 
    // ... 
    Request: { 
     //.. 
    } 
    }; 
} 

module.exports = initErrors(); 

tôi tạo ra một mô-đun riêng biệt chứa các lớp này.

Sau đó, trong việc thực hiện của tôi, tôi có thể bắt lỗi như cá nhân này:

function foo(request, reply) { 

    return bluebird 
    .resolve(bar) 
    .then(reply) 

    .catch(Errors.Parameter.Missing.predicate, function() { 
     return reply(boom.badRequest()); 
    }) 

    .catch(Errors.Entity.NotFound.predicate, function() { 
     return reply({}).code(204); 
    }) 

    .catch(Errors.Entity.IllegalState.predicate, function (error) { 
     return reply(boom.badImplementation(error.message)); 
    }) 

    // any other error 
    .catch(function (error) { 
     return reply(boom.badImplementation(error.message)); 
    }); 
} 

Throwing

Errors.Entity.IllegalState.throw(['foo', 'bar']); 
// or 
throw Errors.Entity.IllegalState.new(['foo', 'bar']); 

Yêu cầu

Errors = require('errors'); // all 
EntityErors = require('errors').Entity; // one group 
EntityNotFoundError = require('errors').Entity.NotFound; // one particular 

Điều duy nhất những gì tôi vẫn không hiểu id tại sao cần sử dụng hàm vị ngữ thay vì chỉ truyền đối tượng lỗi cho catc mệnh đề h. Nhưng tôi có thể sống với điều đó.

3

bạn cũng có thể sử dụng chức năng ngữ với bắt

function isMyCustomError(f) { 
    return f instanceof Error && f.name === "MyCustomError"; 
} 
+0

Hi Esailija, vì tôi không đăng nhập trong một vài ngày danh tiếng đã tự động bị gán cho bạn. May mắn cho bạn, nhưng kể từ khi bạn là nhà phát triển của bluebird bạn khá xứng đáng với nó :) Mã: Tôi không thấy điểm của bạn như thế nào điều này chấp thuận việc xử lý? Bạn nói về xử lý try-catch cổ điển không phân biệt bluebird? –

+0

@ChristopherĐiều này là dành cho bluebird chỉ – Esailija

+0

Vì vậy, đây là chính xác những gì tôi đang làm trong ví dụ trên - như 'catch (Errors.Entity.IllegalState.predicate, ..)' –

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