मैं जावास्क्रिप्ट में एक कस्टम त्रुटि कैसे बनाऊं?


215

किसी कारण से ऐसा लगता है कि कंस्ट्रक्टर प्रतिनिधिमंडल निम्नलिखित स्निपेट में काम नहीं करता है:

function NotImplementedError() { 
  Error.apply(this, arguments); 
}
NotImplementedError.prototype = new Error();

var nie = new NotImplementedError("some message");
console.log("The message is: '"+nie.message+"'")

इसको चलाने से मिलता है The message is: ''। किसी भी विचार क्यों, या अगर एक नया Errorउपवर्ग बनाने का एक बेहतर तरीका है ? वहाँ applyदेशी Errorनिर्माता के लिए आईएनजी के साथ एक समस्या है जिसके बारे में मुझे पता नहीं है?


क्या आपके इंस्टॉलेशन के बाद nI instof NotImplementedError अभिकथन कार्य करता है? मैंने सोचा था कि काम करने के लिए आपको NotImplementedError.prototyp.constructor को स्पष्ट रूप से परिभाषित करने की आवश्यकता है।
जयरोज़ो

अगली बार, कृपया उन सभी बाहरी कोड को फाड़ दें, जिन्हें आपके मुद्दे को प्रदर्शित करने की आवश्यकता नहीं है। इसके अलावा, wtc js.jar है? क्या समस्या को पुन: पेश करने की आवश्यकता है?
बीटी

2
इस प्रश्न को संपादित किया ताकि 10 मिनट के बजाए 10 सेकंड में इसका बोध हो
BT

मैंने एक इनहेरिटेंस / क्लास लाइब्रेरी बनाई, जो एरर टाइप्स से ठीक तरह से इनहेरिट होती है: github.com/fresheneesz/proto
BT

1
शीर्ष उत्तरों में से कुछ के लिए jsfiddle
नैट

जवाबों:


194

अपने प्रोटोटाइप को एरर.प्रोटोटाइप और इंस्टोफॉट और आपके एसेरट्स कार्य को असाइन करने के लिए अपने कोड को अपडेट करें।

function NotImplementedError(message) {
    this.name = "NotImplementedError";
    this.message = (message || "");
}
NotImplementedError.prototype = Error.prototype;

हालाँकि, मैं सिर्फ अपनी खुद की वस्तु फेंकूंगा और सिर्फ नाम की संपत्ति की जांच करूंगा।

throw {name : "NotImplementedError", message : "too lazy to implement"}; 

टिप्पणियों के आधार पर संपादित करें

टिप्पणियों को देखने और यह याद रखने की कोशिश करने के बाद कि मैं अपने लेख में निकोलस ज़कस Error.prototypeकी new Error()तरह प्रोटोटाइप को क्यों सौंपूंगा , मैंने नीचे दिए गए कोड के साथ एक jsFiddle बनाया :

function NotImplementedError(message) {
  this.name = "NotImplementedError";
  this.message = (message || "");
}
NotImplementedError.prototype = Error.prototype;

function NotImplementedError2(message) {
  this.message = (message || "");
}
NotImplementedError2.prototype = new Error();

try {
  var e = new NotImplementedError("NotImplementedError message");
  throw e;
} catch (ex1) {
  console.log(ex1.stack);
  console.log("ex1 instanceof NotImplementedError = " + (ex1 instanceof NotImplementedError));
  console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
  console.log("ex1.name = " + ex1.name);
  console.log("ex1.message = " + ex1.message);
}

try {
  var e = new NotImplementedError2("NotImplementedError2 message");
  throw e;
} catch (ex1) {
  console.log(ex1.stack);
  console.log("ex1 instanceof NotImplementedError2 = " + (ex1 instanceof NotImplementedError2));
  console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
  console.log("ex1.name = " + ex1.name);
  console.log("ex1.message = " + ex1.message);
}

कंसोल आउटपुट यह था।

undefined
ex1 instanceof NotImplementedError = true
ex1 instanceof Error = true
ex1.name = NotImplementedError
ex1.message = NotImplementedError message
Error
    at window.onload (http://fiddle.jshell.net/MwMEJ/show/:29:34)
ex1 instanceof NotImplementedError2 = true
ex1 instanceof Error = true
ex1.name = Error
ex1.message = NotImplementedError2 message

यह "समस्या" की पुष्टि करता है कि मैं भाग गया था त्रुटि का स्टैक गुण लाइन नंबर new Error()था जहां बनाया गया था, और जहां नहीं throw eहुआ था। हालाँकि, यह बेहतर हो सकता है कि NotImplementedError.prototype.name = "NotImplementedError"त्रुटि ऑब्जेक्ट को प्रभावित करने वाली रेखा का साइड इफेक्ट हो ।

इसके अलावा, ध्यान दें NotImplementedError2, जब मैं .nameस्पष्ट रूप से सेट नहीं करता हूं , तो यह "त्रुटि" के बराबर है। हालाँकि, जैसा कि टिप्पणियों में उल्लेख किया गया है, क्योंकि वह संस्करण प्रोटोटाइप सेट करता है new Error(), मैं सेट कर सकता हूं NotImplementedError2.prototype.name = "NotImplementedError2"और ठीक हो सकता हूं ।


45
सबसे अच्छा जवाब, लेकिन Error.prototypeसीधे लेना शायद बुरा रूप है। यदि आप बाद में एक NotImplementedError.prototype.toStringवस्तु जोड़ना चाहते हैं तो उपनाम Error.prototype.toString- करने के लिए बेहतर है NotImplementedError.prototype = new Error()
cdleary

4
मैं अभी भी उन सभी प्रोटोटाइप चीजों में थोड़ा खो गया हूं। आपके उदाहरण में आप इस नाम को क्यों निर्दिष्ट करते हैं? क्या आप इसका उत्तर दे सकते हैं, यह मेरी समझ के लिए महत्वपूर्ण है :)
जयरोज़ो

27
Code.google.com/p/chromium/issues/detail?id=228909 के अनुसार subclass.prototype = new Error()खराब फॉर्म है। आप subclass.prototype = Object.create(superclass.prototype)इसके बजाय उपयोग करने वाले हैं। मुझे उम्मीद है कि यह स्टैक-ट्रेस समस्या को भी ठीक कर सकता है।
गिली

8
अर्थपूर्ण स्टैकट्रेस प्राप्त करने के लिए सरल ट्रिक कंस्ट्रक्टर में त्रुटि उत्पन्न करना और इसे स्टैक को सहेजना है। यह कंस्ट्रक्टर के लिए उचित कॉल स्टैक + 1 लाइन देगा (यह एक उपयुक्त भुगतान है):this.stack = new Error().stack;
मेरेडियन

6
-1; ये गलत है। करना उप-वर्ग के रूप में व्यवहार NotImplementedError.prototype = Error.prototype;नहीं करता है , यह उन्हें ठीक उसी वर्ग के रूप में मानता है । यदि आप उपरोक्त कोड को अपने कंसोल में पेस्ट करते हैं और कोशिश करते हैं कि आपको मिलेगा , जो स्पष्ट रूप से गलत है। instanceofNotImplementedErrorErrorinstanceofnew Error() instanceof NotImplementedErrortrue
मार्क अमेरी

87

उपरोक्त सभी उत्तर भयानक भयानक हैं - वास्तव में। यहां तक ​​कि 107 अप के साथ एक! असली जवाब यहाँ है लोग:

त्रुटि ऑब्जेक्ट से इनहेरिट करना - संदेश गुण कहाँ है?

टी एल; डॉ:

A. कारण messageनिर्धारित नहीं किया जा रहा है, Errorयह एक ऐसा फ़ंक्शन है जो एक नई त्रुटि ऑब्जेक्ट देता है और किसी भी तरह से हेरफेर नहीं करता है this

ख। इस अधिकार को करने का तरीका कंस्ट्रक्टर से आवेदन के परिणाम को वापस करना है, साथ ही सामान्य जटिल जावास्क्रिप्ट तरीके से प्रोटोटाइप को सेट करना है:

function MyError() {
    var temp = Error.apply(this, arguments);
    temp.name = this.name = 'MyError';
    this.message = temp.message;
    if(Object.defineProperty) {
        // getter for more optimizy goodness
        /*this.stack = */Object.defineProperty(this, 'stack', { 
            get: function() {
                return temp.stack
            },
            configurable: true // so you can change it if you want
        })
    } else {
        this.stack = temp.stack
    }
}
//inherit prototype using ECMAScript 5 (IE 9+)
MyError.prototype = Object.create(Error.prototype, {
    constructor: {
        value: MyError,
        writable: true,
        configurable: true
    }
});

var myError = new MyError("message");
console.log("The message is: '" + myError.message + "'"); // The message is: 'message'
console.log(myError instanceof Error); // true
console.log(myError instanceof MyError); // true
console.log(myError.toString()); // MyError: message
console.log(myError.stack); // MyError: message \n 
// <stack trace ...>


 
//for EMCAScript 4 or ealier (IE 8 or ealier), inherit prototype this way instead of above code:
/*
var IntermediateInheritor = function() {};
IntermediateInheritor.prototype = Error.prototype;
MyError.prototype = new IntermediateInheritor();
*/

आप शायद tmpकेवल stackऔर केवल स्पष्ट रूप से सेट करने के बजाय उन्हें सेट करने के लिए त्रुटि के सभी गैर-गुणांक गुणों के माध्यम से गणना करने के लिए कुछ प्रवंचना कर सकते हैं message, लेकिन </ 9 में प्रवंचना समर्थित नहीं है


2
यह समाधान मौजूदा त्रुटि के साथ एक कस्टम त्रुटि को तत्काल करने के लिए भी काम करता है। यदि आप किसी तृतीय पक्ष लाइब्रेरी का उपयोग कर रहे हैं और अपने स्वयं के कस्टम प्रकार के साथ मौजूदा त्रुटि को लपेटना चाहते हैं, तो अन्य विधियां ठीक से काम नहीं करती हैं। FYI करें, आप मौजूदा त्रुटि को पास करके वेनिला त्रुटियों को तुरंत समाप्त कर सकते हैं।
काइल म्यूलर

1
आपको return thisएक निर्माता में नहीं होना चाहिए ।
ओनूर येल्ड्रिम्म

13
मैंने इस दृष्टिकोण को थोड़ा सरल और बेहतर बनाया: jsbin.com/rolojuhuya/1/edit?js,console
Matt Kantor

3
@MattKantor शायद यह एक जवाब है? मुझे लगता है कि मुझे तुम्हारा सबसे अच्छा लगता है।
मपिसोट

2
इसके बजाय temp.name = this.name = 'MyError', आप कर सकते हैं temp.name = this.name = this.constructor.name। इस तरह यह उपवर्गों के लिए भी काम करेगा MyError
जो लिस

45

ES2015 में, आप classइसे सफाई से करने के लिए उपयोग कर सकते हैं :

class NotImplemented extends Error {
  constructor(message = "", ...args) {
    super(message, ...args);
    this.message = message + " has not yet been implemented.";
  }
}

यह वैश्विक संशोधित नहीं करता है Errorप्रोटोटाइप, आप अनुकूलित करने के लिए अनुमति देता है message, name, और अन्य विशेषताओं, और ठीक से ढेर कैप्चर करता है। यह भी बहुत पठनीय है।

बेशक, आपको एक उपकरण का उपयोग करने की आवश्यकता हो सकती है जैसे babelकि आपका कोड पुराने ब्राउज़रों पर चल रहा होगा।


23

यदि कोई कस्टम त्रुटि बनाने और स्टैक ट्रेस प्राप्त करने के बारे में उत्सुक है :

function CustomError(message) {
  this.name = 'CustomError';
  this.message = message || '';
  var error = new Error(this.message);
  error.name = this.name;
  this.stack = error.stack;
}
CustomError.prototype = Object.create(Error.prototype);

try {
  throw new CustomError('foobar');
}
catch (e) {
  console.log('name:', e.name);
  console.log('message:', e.message);
  console.log('stack:', e.stack);
}

7

मानक का यह खंड बता सकता है कि Error.applyकॉल ऑब्जेक्ट को इनिशियलाइज़ क्यों नहीं करता है:

15.11.1 त्रुटि कंस्ट्रक्टर को एक फ़ंक्शन के रूप में कहा जाता है

जब एरर को एक कंस्ट्रक्टर के बजाय फंक्शन के रूप में कहा जाता है, तो यह एक नए एरर ऑब्जेक्ट को बनाता और इनिशिएट करता है। इस प्रकार फ़ंक्शन कॉल एरर (...) एक ही तर्कों के साथ ऑब्जेक्ट क्रिएशन एक्सप्रेशन नई एरर (...) के बराबर है।

इस मामले में Errorफ़ंक्शन संभवतः यह निर्धारित करता है कि इसे एक निर्माता के रूप में नहीं बुलाया जा रहा है, इसलिए यह thisऑब्जेक्ट को इनिशियलाइज़ करने के बजाय एक नया त्रुटि उदाहरण देता है ।

निम्नलिखित कोड के साथ परीक्षण से पता चलता है कि यह वास्तव में हो रहा है:

function NotImplementedError() { 
   var returned = Error.apply(this, arguments);
   console.log("returned.message = '" + returned.message + "'");
   console.log("this.message = '" + this.message + "'");
}
NotImplementedError.prototype = new Error();

var nie = new NotImplementedError("some message");

निम्न आउटपुट उत्पन्न होता है जब यह चलाया जाता है:

returned.message = 'some message'
this.message = ''

इसे कस्टम त्रुटि वर्ग के साथ कैसे जोड़ा जा सकता है? उदाहरण के लिए, मेरे कस्टम एरर क्लास को एक फंक्शन के रूप में कैसे इस्तेमाल किया जा सकता है जो एक इंस्ट्रूमेंट और एक कंस्ट्रक्टर के रूप में बनता है?
ली हेस

नहीं, यह सच नहीं है। यदि यह एक नया त्रुटि उदाहरण देता है, तो उसका संदेश संपत्ति काम करेगा।
बीटी

@BT नए उदाहरण पर msg संपत्ति में msg संपत्ति को कैसे प्रभावित करता thisहै Error.apply(this, arguments);? मैं कह रहा हूँ कि यहाँ त्रुटि के लिए कॉल एक नई वस्तु का निर्माण कर रहा है, जिसे फेंक दिया गया है; पहले से निर्मित वस्तु को आरंभीकृत नहीं करना, जिसे सौंपा गया है nie
डेव

@BT मैंने कुछ उदाहरण कोड जोड़े हैं जो उम्मीद करते हैं कि मैं जो कहना चाह रहा था वह स्पष्ट हो गया है।
डेव

@ क्या मुझे यहाँ उद्देश्य की गलतफहमी हो सकती है, लेकिन क्या आपके NotImplementedErrorकार्यान्वयन से returnedवैरिएबल वापस नहीं आना चाहिए ?
गोरा

7
function InvalidValueError(value, type) {
    this.message = "Expected `" + type.name + "`: " + value;
    var error = new Error(this.message);
    this.stack = error.stack;
}
InvalidValueError.prototype = new Error();
InvalidValueError.prototype.name = InvalidValueError.name;
InvalidValueError.prototype.constructor = InvalidValueError;

3
यह यहाँ का सबसे अच्छा जवाब है। यह आत्महत्या है और इस तरह से बनाया गया अपवाद सभी स्थितियों में सही व्यवहार करेगा। यह स्टैक ट्रेस को भी संरक्षित करता है जो गैर तुच्छ अनुप्रयोगों में बहुत महत्वपूर्ण है। मैं केवल "प्रोटोटाइप = नई त्रुटि ()" "प्रोटोटाइप = Object.create (Error.prototyp)" से बदलूंगा। Node.js के लिए एक छोटा पुस्तकालय है जो आपके लिए ऐसा करता है: npmjs.com/package/node-custom-errors
Lukasz

6

मेरा भी इसी तरह का मुद्दा था। मेरे त्रुटि जरूरतों एक होने के लिए instanceofदोनों Errorऔर NotImplemented, और यह भी कंसोल में एक सुसंगत पश्व-अनुरेखन का उत्पादन करने की जरूरत है।

मेरा समाधान:

var NotImplemented = (function() {
  var NotImplemented, err;
  NotImplemented = (function() {
    function NotImplemented(message) {
      var err;
      err = new Error(message);
      err.name = "NotImplemented";
      this.message = err.message;
      if (err.stack) this.stack = err.stack;
    }
    return NotImplemented;
  })();
  err = new Error();
  err.name = "NotImplemented";
  NotImplemented.prototype = err;

  return NotImplemented;
}).call(this);

// TEST:
console.log("instanceof Error: " + (new NotImplemented() instanceof Error));
console.log("instanceof NotImplemented: " + (new NotImplemented() instanceofNotImplemented));
console.log("message: "+(new NotImplemented('I was too busy').message));
throw new NotImplemented("just didn't feel like it");

नोड.जेएस के साथ चलने का परिणाम:

instanceof Error: true
instanceof NotImplemented: true
message: I was too busy

/private/tmp/t.js:24
throw new NotImplemented("just didn't feel like it");
      ^
NotImplemented: just didn't feel like it
    at Error.NotImplemented (/Users/colin/projects/gems/jax/t.js:6:13)
    at Object.<anonymous> (/Users/colin/projects/gems/jax/t.js:24:7)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:487:10)
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)

त्रुटि मेरे सभी मानदंडों से गुजरती है, और हालांकि stackसंपत्ति गैर-मानक है, यह सबसे नए ब्राउज़रों में समर्थित है जो मेरे मामले में स्वीकार्य है।


5

जॉयंट में जाने से आपको स्टैक प्रॉपर्टी के साथ खिलवाड़ नहीं करना चाहिए (जो कि मैं यहां दिए गए बहुत सारे उत्तरों को देखता हूं), क्योंकि इसका प्रदर्शन पर नकारात्मक प्रभाव पड़ेगा। यहाँ वे कहते हैं:

स्टैक: आम तौर पर, इसके साथ गड़बड़ न करें। यह भी वृद्धि मत करो। V8 केवल इसकी गणना करता है यदि कोई व्यक्ति वास्तव में संपत्ति पढ़ता है, जो प्रदर्शन योग्य त्रुटियों के लिए नाटकीय रूप से सुधार करता है। यदि आप संपत्ति को सिर्फ इसे बढ़ाने के लिए पढ़ते हैं, तो आपको लागत का भुगतान करना होगा, भले ही आपके कॉलर को स्टैक की आवश्यकता न हो।

मुझे पसंद है और मूल त्रुटि को लपेटने के उनके विचार का उल्लेख करना चाहूंगा जो स्टैक पर पारित होने के लिए एक अच्छा प्रतिस्थापन है।

तो यहाँ बताया गया है कि मैं एक कस्टम त्रुटि कैसे बना सकता हूँ, उपर्युक्त पर विचार करना:

es5 संस्करण:

function RError(options) {
    options = options || {}; // eslint-disable-line no-param-reassign
    this.name = options.name;
    this.message = options.message;
    this.cause = options.cause;

    // capture stack (this property is supposed to be treated as private)
    this._err = new Error();

    // create an iterable chain
    this.chain = this.cause ? [this].concat(this.cause.chain) : [this];
}
RError.prototype = Object.create(Error.prototype, {
    constructor: {
        value: RError,
        writable: true,
        configurable: true
    }
});

Object.defineProperty(RError.prototype, 'stack', {
    get: function stack() {
        return this.name + ': ' + this.message + '\n' + this._err.stack.split('\n').slice(2).join('\n');
    }
});

Object.defineProperty(RError.prototype, 'why', {
    get: function why() {
        var _why = this.name + ': ' + this.message;
        for (var i = 1; i < this.chain.length; i++) {
            var e = this.chain[i];
            _why += ' <- ' + e.name + ': ' + e.message;
        }
        return _why;
    }
});

// usage

function fail() {
    throw new RError({
        name: 'BAR',
        message: 'I messed up.'
    });
}

function failFurther() {
    try {
        fail();
    } catch (err) {
        throw new RError({
            name: 'FOO',
            message: 'Something went wrong.',
            cause: err
        });
    }
}

try {
    failFurther();
} catch (err) {
    console.error(err.why);
    console.error(err.stack);
    console.error(err.cause.stack);
}

es6 संस्करण:

class RError extends Error {
    constructor({name, message, cause}) {
        super();
        this.name = name;
        this.message = message;
        this.cause = cause;
    }
    [Symbol.iterator]() {
        let current = this;
        let done = false;
        const iterator = {
            next() {
                const val = current;
                if (done) {
                    return { value: val, done: true };
                }
                current = current.cause;
                if (!val.cause) {
                    done = true;
                }
                return { value: val, done: false };
            }
        };
        return iterator;
    }
    get why() {
        let _why = '';
        for (const e of this) {
            _why += `${_why.length ? ' <- ' : ''}${e.name}: ${e.message}`;
        }
        return _why;
    }
}

// usage

function fail() {
    throw new RError({
        name: 'BAR',
        message: 'I messed up.'
    });
}

function failFurther() {
    try {
        fail();
    } catch (err) {
        throw new RError({
            name: 'FOO',
            message: 'Something went wrong.',
            cause: err
        });
    }
}

try {
    failFurther();
} catch (err) {
    console.error(err.why);
    console.error(err.stack);
    console.error(err.cause.stack);
}

मैंने अपना समाधान एक मॉड्यूल में रखा है, यहाँ यह है: https://www.npmjs.com/package/rerror


3

मैं इसे इस तरह करना पसंद करता हूं:

  • नाम का उपयोग करें ताकि स्ट्रिंग () फेंकता है"{code}: {message}"
  • सुपर में एक ही चीज़ लौटाएं ताकि स्टैकट्रेस में वही दिखाई दे
  • कोड को error.codeचेक / पार्सिंग के रूप में संलग्न करना एक संदेश की जांच करने से बेहतर है कोड में, जिसे आप उदाहरण के लिए स्थानीय बनाना चाहते हैं
  • error.messageएक विकल्प के रूप में संदेश संलग्न करेंerror.toString()

class AppException extends Error {
  constructor(code, message) {
    const fullMsg = message ? `${code}: ${message}` : code;
    super(fullMsg);
    this.name = code;
    this.code = code;
    this.message = fullMsg;
  }
  
  toString() {
    return this.message;
  }
}

// Just a code
try {
  throw new AppException('FORBIDDEN');
} catch(e) {
  console.error(e);
  console.error(e.toString());
  console.log(e.code === 'FORBIDDEN');
}

// A code and a message
try {
  throw new AppException('FORBIDDEN', 'You don\'t have access to this page');
} catch(e) {
  console.error(e);
  console.error(e.toString());
  console.log(e.code === 'FORBIDDEN');
}


2

मुझे बस कुछ इस तरह से लागू करना था और यह पाया कि स्टैक मेरी अपनी त्रुटि कार्यान्वयन में खो गया था। मुझे जो करना था वह एक डमी त्रुटि बनाने और उस से स्टैक को पुनः प्राप्त करने के लिए किया गया था:

My.Error = function (message, innerException) {
    var err = new Error();
    this.stack = err.stack; // IMPORTANT!
    this.name = "Error";
    this.message = message;
    this.innerException = innerException;
}
My.Error.prototype = new Error();
My.Error.prototype.constructor = My.Error;
My.Error.prototype.toString = function (includeStackTrace) {
    var msg = this.message;
    var e = this.innerException;
    while (e) {
        msg += " The details are:\n" + e.message;
        e = e.innerException;
    }
    if (includeStackTrace) {
        msg += "\n\nStack Trace:\n\n" + this.stack;
    }
    return msg;
}

यह संदेश सेट नहीं करता है
BT

2

मैंने नई त्रुटि ऑब्जेक्ट बनाने के लिए कंस्ट्रक्टर पैटर्न का उपयोग किया। मैंने एक उदाहरण के रूप में प्रोटोटाइप श्रृंखला को परिभाषित किया Error। MDN त्रुटि निर्माता संदर्भ देखें ।

आप इस पर इस स्निपेट की जांच कर सकते सार

कार्यान्वयन

// Creates user-defined exceptions
var CustomError = (function() {
  'use strict';

  //constructor
  function CustomError() {
    //enforces 'new' instance
    if (!(this instanceof CustomError)) {
      return new CustomError(arguments);
    }
    var error,
      //handles the arguments object when is passed by enforcing a 'new' instance
      args = Array.apply(null, typeof arguments[0] === 'object' ? arguments[0] : arguments),
      message = args.shift() || 'An exception has occurred';

    //builds the message with multiple arguments
    if (~message.indexOf('}')) {
      args.forEach(function(arg, i) {
        message = message.replace(RegExp('\\{' + i + '}', 'g'), arg);
      });
    }

    //gets the exception stack
    error = new Error(message);
    //access to CustomError.prototype.name
    error.name = this.name;

    //set the properties of the instance
    //in order to resemble an Error instance
    Object.defineProperties(this, {
      stack: {
        enumerable: false,
        get: function() { return error.stack; }
      },
      message: {
        enumerable: false,
        value: message
      }
    });
  }

  // Creates the prototype and prevents the direct reference to Error.prototype;
  // Not used new Error() here because an exception would be raised here,
  // but we need to raise the exception when CustomError instance is created.
  CustomError.prototype = Object.create(Error.prototype, {
    //fixes the link to the constructor (ES5)
    constructor: setDescriptor(CustomError),
    name: setDescriptor('JSU Error')
  });

  function setDescriptor(value) {
    return {
      configurable: false,
      enumerable: false,
      writable: false,
      value: value
    };
  }

  //returns the constructor
  return CustomError;
}());

उपयोग

CustomError निर्माता संदेश बनाने के लिए कई तर्क प्राप्त कर सकता है, जैसे

var err1 = new CustomError("The url of file is required"),
    err2 = new CustomError("Invalid Date: {0}", +"date"),
    err3 = new CustomError("The length must be greater than {0}", 4),
    err4 = new CustomError("Properties .{0} and .{1} don't exist", "p1", "p2");

throw err4;

और यह है कि कस्टम त्रुटि कैसे दिखती है:

कस्टम त्रुटि प्रोटोटाइप श्रृंखला


जो नीचे गिरा, क्या आपके पास तर्क हैं, या नीचे मतदान करने का एक कारण है? या सिर्फ कोड में इरादा समझ में नहीं आता है।
jherax

मैंने अभी देखा कि इस पृष्ठ को ब्राउज़ किए बिना गलती से मैंने डाउनवोट बटन पर क्लिक कर दिया होगा (संभवतः मेरे फोन से ब्राउज़िंग)। मैंने केवल अपना इतिहास ब्राउज़ करते समय आज ही देखा। यह निश्चित रूप से जानबूझकर नहीं था लेकिन मैं इसे पूर्ववत नहीं कर सकता क्योंकि यह अनुग्रह अवधि से अधिक है। आपने एक सूचनात्मक उत्तर दिया और निश्चित रूप से इसके लायक नहीं हैं। यदि आप एक संपादन करते हैं तो मैं खुशी से नीचे की ओर पूर्ववत कर दूंगा। उसके लिए माफ़ करना।
jschr

1

कंस्ट्रक्टर को फैक्ट्री विधि की तरह होना चाहिए और जो आप चाहते हैं उसे वापस करें। यदि आपको अतिरिक्त तरीकों / गुणों की आवश्यकता है, तो आप इसे वापस करने से पहले ऑब्जेक्ट में जोड़ सकते हैं।

function NotImplementedError(message) { return new Error("Not implemented", message); }

x = new NotImplementedError();

हालांकि मुझे यकीन नहीं है कि आपको ऐसा करने की आवश्यकता क्यों होगी। सिर्फ उपयोग क्यों नहीं new Error...? कस्टम अपवाद वास्तव में जावास्क्रिप्ट में बहुत कुछ नहीं जोड़ते हैं (या शायद किसी भी अप्रकाशित भाषा)।


2
आपको जावास्क्रिप्ट में त्रुटि-प्रकार-पदानुक्रम या ऑब्जेक्ट-वैल्यू पर स्विच करना होगा क्योंकि आप केवल एक ही कैच ब्लॉक को निर्दिष्ट कर सकते हैं। आपके समाधान में, (x इंस्टाफ़ॉट NotImplementedError) गलत है, जो मेरे मामले में स्वीकार्य नहीं है।
cdleary

1

यह अच्छी तरह से सीज़ेरियन डेवलपर में लागू किया गया है:

इसका सरलीकृत रूप है:

var NotImplementedError = function(message) {
    this.name = 'NotImplementedError';
    this.message = message;
    this.stack = (new Error()).stack;
}

// Later on...

throw new NotImplementedError();

यह महान काम करता है, सिवाय इसके कि स्टैक में त्रुटि निर्माता के लिए एक अतिरिक्त रेखा होगी, जो एक समस्या हो सकती है।
SystemParadox

इसके अलावा, error instanceof Errorपरीक्षण पास नहीं करता है , जो सहायक हो सकता है।
लॉरेन

1

यह मेरा कार्यान्वयन है:

class HttpError extends Error {
  constructor(message, code = null, status = null, stack = null, name = null) {
    super();
    this.message = message;
    this.status = 500;

    this.name = name || this.constructor.name;
    this.code = code || `E_${this.name.toUpperCase()}`;
    this.stack = stack || null;
  }

  static fromObject(error) {
    if (error instanceof HttpError) {
      return error;
    }
    else {
      const { message, code, status, stack } = error;
      return new ServerError(message, code, status, stack, error.constructor.name);
    }
  }

  expose() {
    if (this instanceof ClientError) {
      return { ...this };
    }
    else {
      return {
        name: this.name,
        code: this.code,
        status: this.status,
      }
    }
  }
}

class ServerError extends HttpError {}

class ClientError extends HttpError { }

class IncorrectCredentials extends ClientError {
  constructor(...args) {
    super(...args);
    this.status = 400;
  }
}

class ResourceNotFound extends ClientError {
  constructor(...args) {
    super(...args);
    this.status = 404;
  }
}

उदाहरण उपयोग # 1:

app.use((req, res, next) => {
  try {
    invalidFunction();
  }
  catch (err) {
    const error = HttpError.fromObject(err);
    return res.status(error.status).send(error.expose());
  }
});

उदाहरण उपयोग # 2:

router.post('/api/auth', async (req, res) => {
  try {
    const isLogged = await User.logIn(req.body.username, req.body.password);

    if (!isLogged) {
      throw new IncorrectCredentials('Incorrect username or password');
    }
    else {
      return res.status(200).send({
        token,
      });
    }
  }
  catch (err) {
    const error = HttpError.fromObject(err);
    return res.status(error.status).send(error.expose());
  }
});

0

उपयोग करने में सक्षम नहीं होने की कीमत पर instanceof, निम्नलिखित मूल स्टैक ट्रेस को संरक्षित करता है और किसी भी गैर-मानक चाल का उपयोग नहीं करता है।

// the function itself
var fixError = function(err, name) {
    err.name = name;
    return err;
}

// using the function
try {
    throw fixError(new Error('custom error message'), 'CustomError');
} catch (e) {
    if (e.name == 'CustomError')
        console.log('Wee! Custom Error! Msg:', e.message);
    else
        throw e; // unhandled. let it propagate upwards the call stack
}

आप सभी यहाँ उदाहरण का उपयोग करने में सक्षम होने के लिए क्या करना चाहते हैं, सिर्फ फिक्स के बजाय नया फिक्स फेंकना है
BT

@ बीटी: fixErrorऊपर दिए गए फ़ंक्शन के साथ नहीं । newकॉल करते समय इसे जोड़ने से बस एक ऐसी वस्तु बन जाएगी जो फेंक दी जाती है।
टीजे क्राउडर

ओह, मुझे लगता है कि मैं "Instof FixError" का उपयोग करने का मतलब था - तो "Instof त्रुटि" काम नहीं करेगा .. मुझे लगता है कि बदतर है ..
BT

0

एक अन्य विकल्प, सभी वातावरण में काम नहीं कर सकता। कम से कम यह आश्वासन दिया है कि यह नोड्ज 0.8 में काम करता है। यह दृष्टिकोण आंतरिक प्रोटो प्रोप को संशोधित करने के एक गैर मानक तरीके का उपयोग करता है

function myError(msg){ 
      var e = new Error(msg); 
      _this = this; 
      _this.__proto__.__proto__ = e;
}

0

यदि आप Node / Chrome का उपयोग कर रहे हैं। निम्नलिखित स्निपेट आपको विस्तार देगा जो निम्नलिखित आवश्यकताओं को पूरा करता है।

  • err instanceof Error
  • err instanceof CustomErrorType
  • [CustomErrorType]संदेश के साथ बनाए जाने पर दिलासा देता है
  • [CustomErrorType: message]संदेश के बिना बनाए जाने पर कंसोल.लॉग () रिटर्न
  • थ्रो / स्टैक उस बिंदु पर जानकारी प्रदान करता है जिस पर त्रुटि हुई थी।
  • Node.JS और Chrome में बेहतर तरीके से काम करता है।
  • क्रोम, सफारी, फ़ायरफ़ॉक्स और IE 8+ में इंस्टॉफ़ चेक पास करेगा, लेकिन क्रोम / सफारी के बाहर वैध स्टैक नहीं होगा। मैं इसके साथ ठीक हूं क्योंकि मैं क्रोम में डीबग कर सकता हूं, लेकिन विशिष्ट त्रुटि प्रकारों की आवश्यकता वाले कोड अभी भी क्रॉस ब्राउज़र को कार्य करेंगे। यदि आपको केवल नोड की आवश्यकता है तो आप आसानी से ifस्टेटमेंट निकाल सकते हैं और जाने के लिए अच्छा है

टुकड़ा

var CustomErrorType = function(message) {
    if (Object.defineProperty) {
        Object.defineProperty(this, "message", {
            value : message || "",
            enumerable : false
        });
    } else {
        this.message = message;
    }

    if (Error.captureStackTrace) {
        Error.captureStackTrace(this, CustomErrorType);
    }
}

CustomErrorType.prototype = new Error();
CustomErrorType.prototype.name = "CustomErrorType";

प्रयोग

var err = new CustomErrorType("foo");

उत्पादन

var err = new CustomErrorType("foo");
console.log(err);
console.log(err.stack);

[CustomErrorType: foo]
CustomErrorType: foo
    at Object.<anonymous> (/errorTest.js:27:12)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:906:3

/errorTest.js:30
        throw err;
              ^
CustomErrorType: foo
    at Object.<anonymous> (/errorTest.js:27:12)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:906:3

0

निम्नलिखित मेरे लिए आधिकारिक मोज़िला प्रलेखन त्रुटि से लिया गया काम किया ।

function NotImplementedError(message) {
    var instance = new Error(message);
    instance.name = 'NotImplementedError';

    Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
    if (Error.captureStackTrace) {
        Error.captureStackTrace(instance, NotImplementedError);
    }
    return instance;
}

NotImplementedError.prototype = Object.create(Error.prototype, {
    constructor: {
        value: Error,
        enumerable: false,
        writable: true,
        configurable: true
    }
});

-1

उपयोगकर्ता परिभाषित त्रुटि प्रकार के प्रत्येक उदाहरण के लिए एक नया प्रोटोटाइप ऑब्जेक्ट आज़माएं। यह instanceofसामान्य प्लस प्रकार के रूप में व्यवहार करने की अनुमति देता है और फ़ायरफ़ॉक्स और V8 (चोम, नोडज) में संदेश को सही ढंग से सूचित किया जाता है।

function NotImplementedError(message){
    if(NotImplementedError.innercall===undefined){
        NotImplementedError.innercall = true;
        NotImplementedError.prototype = new Error(message);
        NotImplementedError.prototype.name = "NotImplementedError";
        NotImplementedError.prototype.constructor = NotImplementedError;

        return new NotImplementedError(message);
    }
    delete NotImplementedError.innercall;
}

ध्यान दें कि एक अतिरिक्त प्रविष्टि अन्यथा सही स्टैक को आगे बढ़ाएगी।


काम नहीं करता है। प्रयास करें: var a = new NotImplementedError('a'), b = new NotImplementedError('b');। अब a instanceof NotImplementedError == falseऔरb instanceof NotImplementedError == true
jjrv

-1

यह इसे करने का सबसे तेज़ तरीका है:

    let thisVar = false

    if (thisVar === false) {
            throw new Error("thisVar is false. It should be true.")
    }

-3

आसान तरीका है। आप अपने ऑब्जेक्ट को त्रुटि ऑब्जेक्ट से इनहेरिट कर सकते हैं। उदाहरण:

function NotImplementError(message)
{
    this.message = message;
    Error.call();
    Error.call(message);
} 

हम जो कर रहे हैं वह फ़ंक्शन कॉल () का उपयोग कर रहा है, जो त्रुटि वर्ग के निर्माता को कॉल करता है, इसलिए मूल रूप से अन्य ऑब्जेक्ट ओरिएंटेड भाषाओं में क्लास इनहेरिटेंस को लागू करने के समान है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.