Altnivela try / catch / fine en Ĝavaskripto kaj Tajpskribo

Rigardu detale la efektivigon de provo-kaptaĵo-fine-bloko

Eraro-pritraktado en Ĝavaskripto kaj Tajposkripto

Kiam ajn eraro okazas dum rultempo, ĝi estas "ĵetita" en Ĝavaskripto kaj Tajposkripto, kiel ĝi okazas en plej multaj programlingvoj. Ne traktataj ĵetitaj eraroj kaŭzos kraŝon de via programo aŭ servo, do la plej malbonan eblan sperton de uzanto. Se eraro okazas, iu ajn nesavita progreso perdiĝas kaj uzantoj eble povus komenci longan procezon (ekzemple, se uzanto enskribiĝis al platformo provizante multajn informojn) denove. La rezulto estas, ke tiuj uzantoj plej verŝajne neniam plu uzos vian produkton, ĉar fido perdiĝis.

Por trakti tiajn kazojn, eraro povas esti "kaptita". Por kapti erarojn en Ĝavaskripto kaj Tajpskribo, vi simple envolvas vian kodon per "provu" -bloko, sekvita per "kapti" -bloko.

async function getData(){
  try {
    // Call a dummy async 'fetch'-functoin
    const result = await fetch();
    return { result };
  } catch(error) {
    return { error };
  }
}

// ... later in your code ....

const { result, error } = await getData();

if (error){
  // ... handle error case.
}

// Access the results.

La rezulto estas, ke la eraro ne disvastiĝos tra la tuta sistemo, kio kaŭzas la kraŝon, sed estos pritraktita rekte en la amplekso de via kodo. La programo aŭ servo ne fiaskos kaj mildiga strategio por procesi la eraron povas esti aplikita.

Speciala uzado per la "fine" -bloko

Kiel ekstra paŝo por trakti erarojn, Ĝavaskripto kaj Tajpskribo donas aldonan "finfine" -ŝlosilvorton. Tia "fine" -bloko ekzekutas iun ajn kodon ene de sia amplekso post kiam ambaŭ la "try" -bloko kaj la "catch" -bloko ekzekutiĝis (se eraro okazis).

// This function is absolutely save
// to call. It fetches some data and 
// optionally catches a potential error.
//
// After everything's done, a 'finally'
// sends the error to our backend for logs,
// if there was any.
async function getData(){
  // In this case, we store the result
  // and error in mutable variables,
  // then return both.
  let result: Result;
  let error: Error;
  
  try {
    // Call a dummy async 'fetch'-function
    result = await fetch();
  } catch(e) {
    error = e;
  } finally {
    // After the whole try/catch has been
    // processed, we can log the error.
    if(error){
      await trackErrorInCloud(error);
    }
  }
  
  return { result, error };
}

// ... same as before ...

Sed atendu, estas pli! Ĉu vi sciis, ke la "finfine" -bloko plenumiĝas eĉ se vi redonas rezulton en la "provu" - aŭ "kaptu" -blokon? Jen ekzemplo de tio, kion mi celas per tio.

// Same as the example before, but
// now we directly return from within
// each code block. And this is where
// a side effect can happen.
async function getData(){
  try {
    const result = await fetch();
    return { result };
  } catch(error) {
    return { error }
  } finally {
    //
    // WATCH OUT!
    //
    // Just for demo purpose, but this
    // line of code will override both
    // the return in 'try' as well as 'catch'!
    //
    // Returning inside of 'finally' is therefore
    // dangerous and will lead to hard-to-debug 
    // issues.
    return { finally: true };
  }
}

// data === { finally: true }
const data = await getData();
// Here's a better use case for
// finally.
async function getData(){
  let error: Error;
  
  try {
    const result = await fetch();
    return { result };
  } catch(e) {
    error = e;
    return { error }
  } finally {
    // No return in finally,
    // so it's safe to use.
    if(error){
      await logInCloud()
    }
  }
}

// if no error === { result: ... }
// if error === { error: ... }
const data = await getData();

Resumo

Kiel vi vidis, pritrakti erarojn en Ĝavaskripto kaj Tajpado estas sufiĉe facila kaj evitas kompletan kraŝon de via aplikaĵo. La speciala pritraktado de revenantaj rezultoj en la blokoj "provi" - kaj "kapti" estas bone scii kiam oni uzas la "fine" -blokon, sed ne estu misuzata por eviti efektivigi vian kodon laŭ kontraŭŝablona stilo.