JavaScript'te belirli hataları işleme (istisnaları düşünün)


112

Farklı türdeki hataları nasıl uygularsınız, böylece belirli hataları yakalayabilir ve diğerlerinin kabarmasına izin verebilirsiniz ..?

Bunu başarmanın bir yolu, Errornesnenin prototipini değiştirmektir :

Error.prototype.sender = "";


function throwSpecificError()
{
    var e = new Error();

    e.sender = "specific";

    throw e;
}

Belirli bir hatayı yakalayın:

try
{
    throwSpecificError();
}

catch (e)
{
    if (e.sender !== "specific") throw e;

    // handle specific error
}


Alternatifleriniz var mı?

Yanıtlar:


159

Özel istisnalar oluşturmak için, Error nesnesinden devralabilirsiniz:

function SpecificError () {

}

SpecificError.prototype = new Error();

// ...
try {
  throw new SpecificError;
} catch (e) {
  if (e instanceof SpecificError) {
   // specific error
  } else {
    throw e; // let others bubble up
  }
}

Hatadan miras almadan minimalist bir yaklaşım, bir ada ve bir mesaj özelliklerine sahip basit bir nesneyi fırlatmak olabilir:

function throwSpecificError() {
  throw {
    name: 'SpecificError',
    message: 'SpecificError occurred!'
  };
}


// ...
try {
  throwSpecificError();
} catch (e) {
  if (e.name == 'SpecificError') {
   // specific error
  } else {
    throw e; // let others bubble up
  }
}


5
bu kodla ilgili sorun: } catch (e) { if (e.name == 'SpecificError') { // specific error } else { throw e; // let others bubble up } }IE7'de çalışmaması, "Özel durum atıldı ve yakalanmadı" hatasını ortaya çıkarmasıdır. Aşağıda msdn'den son derece aptalca (her zaman olduğu gibi) açıklama yer almaktadır: "Bir throw ifadesi eklediniz, ancak bu bir try bloğu içine alınmadı veya hatayı yakalamak için ilişkilendirilmiş bir catch bloğu yoktu. Try bloğu içinden istisnalar atılır throw deyimini kullanarak ve bir catch ifadesiyle try bloğunun dışında yakalandı. "
Eugene Kuzmenko

1
Microsoft'un C # kesinlikle hataları Javascript: P'den daha iyi işler. Mozzilla, Firefox'a buna benzer bir şey ekledi. Ecmascript standardında olmasa da, ES6'da bile değil, ama aynı zamanda başarılı olmasa da nasıl uygun hale getirileceğini açıklıyorlar. Temelde yukarıdakiyle aynı, ancak kullanıyor instanceOf. Burayı
Bart

Javascript'te ister basit bir dizge, ister bir sayı (hata kodunu düşünün) veya tam nitelikli bir nesne olsun, istediğinizi atabilirsiniz. Tatlı!
Abraham Brookes

1
@LuisNell, Kod örneğime dikkatlice bakarsanız name, yapıcı işlevinin özelliğini kullanmayı önermediğimi göreceksiniz . nameKırılmayacak özelliğe sahip özel yapılmış bir nesneyi fırlatmayı öneriyordum ...
CMS

15

Aşağıdaki yorumlarda belirtildiği gibi, bu Mozilla'ya özgüdür, ancak 'koşullu yakalama' bloklarını kullanabilirsiniz. Örneğin:

try {
  ...
  throwSpecificError();
  ...
}
catch (e if e.sender === "specific") {
  specificHandler(e);
}
catch (e if e.sender === "unspecific") {
  unspecificHandler(e);
}
catch (e) {
  // don't know what to do
  throw e;
} 

Bu, en azından sözdizimsel olarak Java'da kullanılan tiplendirilmiş istisna işlemeye daha benzer bir şey verir.


CMS'nin cevabıyla birleştirin ve mükemmel.
Ates Goral

3
Koşullu yakalama, daha önce bilmediğim veya unuttuğum bir şey. Beni eğittiğiniz / hatırlattığınız için teşekkürler! +1
Ates Goral

12
Yalnızca Firefox tarafından desteklenir (2.0'dan beri). Diğer tarayıcılarda bile ayrıştırmaz; yalnızca sözdizimi hataları alırsınız.
Crescent Fresh

10
Evet, bu yalnızca Mozilla'ya özgü bir eklentidir, standartlaştırma için bile önerilmemiştir. Sözdizimi düzeyinde bir özellik olarak, onu koklamanın ve isteğe bağlı olarak kullanmanın bir yolu yoktur.
bobince

3
Ek olarak, önerilen çözümün standart dışı olmasıyla ilgili olarak. [Mozilla'nın JavaScript Referansından [( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ) alıntı yapın :This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.
informatik01

10

try-catch-finally.js

Try-catch-last.js kullanarak , _tryişlevi çağıracağı anonim bir geri arama ile çağırabilir ve .catchbelirli hataları yakalamak için aramaları ve .finallyher iki şekilde de çalıştırmak için bir arama zincirini kullanabilirsiniz .

Misal

_try(function () {
    throw 'My error';
})
.catch(Error, function (e) {
    console.log('Caught Error: ' + e);
})
.catch(String, function (e) {
    console.log('Caught String: ' + e);
})
.catch(function (e) {
    console.log('Caught other: ' + e);
})
.finally(function () {
    console.log('Error was caught explicitly');
});

Modern ok işlevlerine ve şablon değişmez değerlerine sahip örnek

_try(() => {
  throw 'My error';
}).catch(Error, e => {
  console.log(`Caught Error: ${e}`);
}).catch(String, e => {
  console.log(`Caught String: ${e}`);
}).catch(e => {
  console.log(`Caught other: ${e}`);
}).finally(() => {
  console.log('Error was caught explicitly');
});

2

İhracat kullanımı için modül

/**
 * Custom InputError
 */
class InputError extends Error {
  /**
   * Create InputError
   * @param {String} message
   */
  constructor(message) {
    super(message);
    this.name = this.constructor.name;
    Error.captureStackTrace(this, this.constructor);
  }
}

/**
 * Custom AuthError
 */
class AuthError extends Error {
  /**
   * Create AuthError
   * @param {String} message
   */
  constructor(message) {
    super(message);
    this.name = this.constructor.name;
    Error.captureStackTrace(this, this.constructor);
  }
}

/**
 * Custom NotFoundError
 */
class NotFoundError extends Error {
  /**
   * Create NotFoundError
   * @param {String} message
   */
  constructor(message) {
    super(message);
    this.name = this.constructor.name;
    Error.captureStackTrace(this, this.constructor);
  }
}

module.exports = {
  InputError: InputError,
  AuthError: AuthError,
  NotFoundError: NotFoundError
};

Komut dosyasına aktar:

const {InputError, AuthError, NotFoundError} = require(path.join(process.cwd(), 'lib', 'errors'));

kullanın:

function doTheCheck = () =>
  checkInputData().then(() => {
    return Promise.resolve();
  }).catch(err => {
    return Promise.reject(new InputError(err));
  });
};

Harici arama kodu:

doTheCheck.then(() => {
  res.send('Ok');
}).catch(err => {
  if (err instanceof NotFoundError) {
    res.status(404).send('Not found');
  } else if (err instanceof AuthError) {
    res.status(301).send('Not allowed');
  } else if (err instanceof InputError) {
    res.status(400).send('Input invalid');
  } else {
    console.error(err.toString());
    res.status(500).send('Server error');
  }
});

0

Bu çözümlerin hiçbirini sevmedim, bu yüzden kendim yaptım. Try-catch-final.js oldukça iyidir, ancak denemeden önce küçük bir alt çizgiyi (_) unutursanız, kod yine de iyi çalışacaktır, ancak hiçbir şey yakalanmayacaktır! Yuck.

CatchFilter

Koduma bir CatchFilter ekledim:

"use strict";

/**
 * This catches a specific error. If the error doesn't match the errorType class passed in, it is rethrown for a
 * different catch handler to handle.
 * @param errorType The class that should be caught
 * @param funcToCall The function to call if an error is thrown of this type
 * @return {Function} A function that can be given directly to the `.catch()` part of a promise.
 */
module.exports.catchOnly = function(errorType, funcToCall) {
  return (error) => {
    if(error instanceof errorType) {
      return funcToCall(error);
    } else {
      // Oops, it's not for us.
      throw error;
    }
  };
};

Şimdi filtreleyebilirim

Şimdi C # veya Java'daki gibi filtreleyebilirim:

new Promise((resolve, reject => {
   <snip><snip>
}).catch(CatchFilter.catchOnly(MyError, err =>
   console.log("This is for my error");
}).catch(err => {
   console.log("This is for all of the other errors.");
});

-2
    <li>
      <span>onWarning:</span>
      <span id="msg_warning"></span>
    </li>

  try {
  // load face detection model
  await changeFaceDetector(MTCNN)
  changeInputSize(128)

  // try to access users webcam and stream the images
  // to the video element

    const stream = await navigator.mediaDevices.getUserMedia({ video: {} })
    const videoEl = $('#inputVideo').get(0)
    videoEl.srcObject = stream
  }
  catch(err) {
    //$("#msg_error").html(`Requested device not found`);
    $("#msg_error").html(err.message);
    console.log(err.message);
  }

Merhaba, StackOverflow'a hoş geldiniz. Cevabınız zaten gönderilmiş olan diğer 5 cevaptan nasıl daha iyi / daha verimli / vb.
mjuarez
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.