Probabil m-am obisnuit cu paradigma de event driven, mi se pare mult mai simplu sa gandesc asa fata de modelul OOP / procedural.
Din ce-am observat multi nu prea fac error handling, nu se diferentiaza intre operational errors si programming (human) errors.
Modelul de error handling este foarte similar cu conceptul event driven. Ai un flow normal de executie pe o serie de task-uri si cand ceva nu este valid faci throw la error. Sunt cazuri in care ai nevoie sa modifici flow-ul cand se intampla o eroare apoi sa dai un raspuns utilizatorului.
Ca exemplu:
Cum gandeam cand scriam php:
Cum gandesc de cand scriu node:
Node’s callback model, error first paradigm and how did we get here
.
Step 1: understand asynchrony brings time, and time flows forward:
Step 2: use a functional model approach: useCaseFunction(input) => output
Step 3: a task (use case) can succeed or fail
Pt. ca error handling-ul este important in node s-a promovat ideea de error first.
// when calling a callback pass the error as the first parameter
↓↓↓↓↓
getUserById(session.id, (error, user) => {
if (error) {
// failure
}
else {
// success
}
})
Callback-urile au fost folosite pt. ca in 2010 nu exista o alta sintaxa prin care se putea folosi modelul asincron. Callback hell a aparut pt. ca majoritatea au facut un nesting prea deep la cod:
onRequest(({ request, session }, reply) => {
getUserById(session.id, (error, user) => {
if (error) {
// failure
}
else {
sendPasswordResetEmail(user.email, (error) => {
if (error) {
// failure
}
else {
logUserActionToAnalytics({ ... }, (error) => {
if (error) {
// failure
}
else {
// success
}
})
}
})
}
})
})
Acum exista async / await + promises care fac codul sa arate mult mai clean.
async function onRequest({ request, reply, session }) {
const user = await getUserById(session.id)
if (!user) {
throw new OperationalError("User was not found")
}
await sendPasswordResetEmail(user.email)
await logUserActionToAnalytics({ ... })
reply({ success: 1 })
}
// where onRequest is called is wrapped in a try / catch block