Menangani kesalahan khusus di JavaScript (pikirkan pengecualian)

112

Bagaimana Anda menerapkan jenis kesalahan yang berbeda, sehingga Anda dapat menangkap kesalahan tertentu dan membiarkan orang lain muncul ..?

Salah satu cara untuk mencapai ini adalah dengan memodifikasi prototipe Errorobjek:

Error.prototype.sender = "";


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

    e.sender = "specific";

    throw e;
}

Tangkap kesalahan khusus:

try
{
    throwSpecificError();
}

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

    // handle specific error
}


Apakah kalian punya alternatif lain?

cllpse.dll
sumber

Jawaban:

159

Untuk membuat pengecualian khusus, Anda dapat mewarisi dari objek Error:

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
  }
}

Pendekatan minimalis, tanpa mewarisi dari Error, dapat berupa melempar objek sederhana yang memiliki nama dan properti pesan:

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
  }
}
CMS
sumber
2
Mewarisi dari Errorbermasalah. Lihat stackoverflow.com/questions/1382107/…
Crescent Fresh
5
masalah dengan kode ini: } catch (e) { if (e.name == 'SpecificError') { // specific error } else { throw e; // let others bubble up } }adalah bahwa itu tidak akan berfungsi di IE7, meningkatkan kesalahan "Pengecualian dilempar dan tidak tertangkap". Berikut ini adalah penjelasan yang sangat bodoh (seperti biasa) dari msdn: "Anda menyertakan pernyataan lemparan, tetapi tidak disertakan dalam blok percobaan, atau tidak ada blok tangkap terkait untuk menjebak kesalahan. Pengecualian dilemparkan dari dalam blok percobaan menggunakan pernyataan lemparan, dan tertangkap di luar blok percobaan dengan pernyataan menangkap. "
Eugene Kuzmenko
1
Yah Microsoft C # pasti menangani kesalahan lebih baik daripada Javascript: P. Mozzilla menambahkan sesuatu seperti itu ke Firefox yang seperti itu. Meskipun tidak ada dalam standar Ecmascript, bahkan tidak ES6, tetapi mereka juga menjelaskan bagaimana membuatnya sesuai, meskipun tidak sesingkat itu. Pada dasarnya sama seperti di atas, tetapi menggunakan instanceOf. Cek di sini
Bart
Dalam Javascript Anda dapat membuang apa pun yang Anda inginkan, baik itu string sederhana, angka (pikirkan kode kesalahan) atau objek yang sepenuhnya memenuhi syarat. Manis!
Abraham Brookes
1
@LuisNell, Jika Anda melihat contoh kode saya dengan hati-hati, Anda akan melihat bahwa saya tidak menyarankan menggunakan nameproperti fungsi konstruktor. Saya menyarankan untuk melempar objek yang dibuat khusus dengan nameproperti, yang tidak akan merusak ...
CMS
15

Seperti disebutkan dalam komentar di bawah ini, ini khusus untuk Mozilla, tetapi Anda dapat menggunakan blok 'tangkap bersyarat'. misalnya:

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;
} 

Ini memberikan sesuatu yang lebih mirip dengan penanganan pengecualian yang diketik yang digunakan di Java, setidaknya secara sintaksis.

Andy
sumber
Gabungkan dengan jawaban CMS dan itu sempurna.
Ates Goral
3
Tangkapan bersyarat adalah sesuatu yang saya tidak tahu sebelumnya atau lupa. Terima kasih telah mendidik / mengingatkan saya! +1
Ates Goral
12
Hanya didukung oleh Firefox (sejak 2.0). Ia bahkan tidak mengurai di browser lain; Anda hanya mendapatkan kesalahan sintaks.
Crescent Fresh
10
Ya, ini adalah ekstensi khusus Mozilla, bahkan tidak diusulkan untuk standardisasi. Menjadi fitur tingkat sintaks, tidak ada cara untuk mengendusnya dan secara opsional juga menggunakannya.
bobince
3
Selain itu, mengenai solusi yang diusulkan tidak standar. Kutipan dari [Referensi JavaScript Mozilla [( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ):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

Menggunakan try-catch-last.js , Anda dapat memanggil _tryfungsi tersebut dengan callback anonim, yang akan dipanggil, dan Anda dapat .catchmenghubungkan panggilan untuk menangkap kesalahan tertentu, dan .finallypanggilan untuk dijalankan dengan cara apa pun.

Contoh

_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');
});

Contoh dengan fungsi panah modern dan literal template

_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');
});
c24w
sumber
2

Modul untuk penggunaan ekspor

/**
 * 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
};

Impor ke dalam skrip:

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

Menggunakan:

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

Kode panggilan eksternal:

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');
  }
});
Hoovinator
sumber
0

Saya tidak menyukai salah satu solusi ini, jadi saya membuatnya sendiri. Try-catch-last.js cukup keren kecuali jika Anda lupa satu garis bawah kecil (_) sebelum mencoba maka kode akan tetap berjalan dengan baik, tetapi tidak akan pernah tertangkap! Yuck.

CatchFilter

Saya menambahkan CatchFilter di kode saya:

"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;
    }
  };
};

Sekarang saya bisa memfilter

Sekarang saya bisa memfilter seperti di C # atau Java:

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.");
});
Ryan Shillington
sumber
-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);
  }
carls eriksen
sumber
Hai, selamat datang di StackOverflow. Bagaimana jawaban Anda lebih baik / lebih efisien / dll dari 5 jawaban lain yang sudah diposting?
mjuarez