Callback Flashcards

(12 cards)

1
Q

Qu’est-ce qu’un callback ?

A

Un callback est une fonction passée en argument à une autre fonction, qui sera exécutée plus tard (après un événement, une opération async, etc.).

Analogie : C’est comme donner votre numéro de téléphone en disant ‘Rappelle-moi quand tu as fini’.

Exemple :

function doSomething(callback) {
  // Faire quelque chose
  callback(); // Exécuter le callback
}

function myCallback() {
  console.log('Callback exécuté!');
}

doSomething(myCallback); // Passer la fonction (sans ())
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Différence entre callback synchrone et asynchrone ?

A

Callback Synchrone :
- Exécuté immédiatement dans le même call stack
- Exemples : forEach, map, filter

[1, 2, 3].forEach(n => console.log(n)); // Sync

Callback Asynchrone :
- Exécuté plus tard, après une opération async
- Exemples : setTimeout, addEventListener, fetch

setTimeout(() => console.log('Async'), 0); // Async
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Qu’est-ce que le callback hell ?

A

Le callback hell (pyramide de la mort) est une situation où les callbacks sont imbriqués profondément, rendant le code difficile à lire et maintenir.

Problème :

getData(a => {
  getData2(a, b => {
    getData3(b, c => {
      getData4(c, d => {
        getData5(d, e => {
          console.log(e);
        });
      });
    });
  });
});

Problèmes :
- Difficile à lire (pyramide)
- Gestion d’erreur complexe
- Difficile à débugger
- Code pas réutilisable

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Quelles sont les solutions au callback hell ?

A

Solution 1 : Named Functions

function handleUser(err, user) {
  if (err) return handleError(err);
  getPostsByUser(user.id, handlePosts);
}

function handlePosts(err, posts) {
  if (err) return handleError(err);
  console.log(posts);
}

getUserById(userId, handleUser);

Solution 2 : Promises

getUserById(userId)
  .then(user => getPostsByUser(user.id))
  .then(posts => console.log(posts))
  .catch(err => console.error(err));

Solution 3 : Async/Await

async function loadData() {
  try {
    const user = await getUserById(userId);
    const posts = await getPostsByUser(user.id);
    console.log(posts);
  } catch (err) {
    console.error(err);
  }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Qu’est-ce que le error-first callback pattern ?

A

Convention Node.js où le premier paramètre du callback est toujours l’erreur (null si succès).

Pattern :

function readFileAsync(filename, callback) {
  // callback(error, result)
  // Si erreur : callback(error, null)
  // Si succès : callback(null, result)
}

Usage :

fs.readFile('file.txt', (err, data) => {
  if (err) {
    console.error('Erreur:', err);
    return; // Important : return pour arrêter
  }

  console.log('Données:', data);
});

Avantages :
- Cohérence dans tout Node.js
- Force la gestion d’erreur
- Clair si erreur ou succès

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Comment éviter de perdre le contexte ‘this’ dans un callback ?

A

Problème :

const obj = {
  name: 'Alice',
  greet() {
    console.log(`Hello, ${this.name}`);
  }
};

setTimeout(obj.greet, 1000); // 'Hello, undefined' ❌

Solutions :

1. Arrow function (Recommandé) :

setTimeout(() => obj.greet(), 1000); // ✅

2. bind :

setTimeout(obj.greet.bind(obj), 1000); // ✅

3. Variable that :

const that = this;
setTimeout(function() {
  that.greet();
}, 1000); // ✅
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Exemples de callbacks dans les Array Methods

A

forEach :

[1, 2, 3].forEach((num, index) => {
  console.log(`Index ${index}: ${num}`);
});

map :

const doubled = [1, 2, 3].map(n => n * 2);
// [2, 4, 6]

filter :

const evens = [1, 2, 3, 4, 5, 6].filter(n => n % 2 === 0);
// [2, 4, 6]

reduce :

const sum = [1, 2, 3, 4].reduce((acc, n) => acc + n, 0);
// 10

Tous ces méthodes prennent une fonction callback.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Comment créer une fonction avec callback pour opération asynchrone ?

A
function delay(ms, callback) {
  setTimeout(callback, ms);
}

// Usage
delay(1000, function() {
  console.log('1 seconde écoulée');
});

// Avec données
function fetchUser(id, callback) {
  setTimeout(function() {
    const user = { id: id, name: 'Alice' };
    callback(null, user); // Error-first
  }, 1000);
}

// Usage
fetchUser(1, function(err, user) {
  if (err) {
    console.error(err);
    return;
  }
  console.log('User:', user);
});
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Quel est le piège avec l’appel multiple d’un callback ?

A

Problème :

function getData(callback) {
  callback('first');
  callback('second'); // ❌ Appelé 2 fois !
}

Un callback ne devrait être appelé qu’une seule fois.

Solution - Safe Callback :

function getData(callback) {
  let called = false;

  function safeCallback(...args) {
    if (called) return;
    called = true;
    callback(...args);
  }

  // Utiliser safeCallback
  safeCallback('first');
  safeCallback('second'); // Ignoré
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Piège : callback parfois sync, parfois async

A

❌ TRÈS MAUVAIS :

function maybeSync(callback) {
  if (cache) {
    callback(cache); // Synchrone
  } else {
    fetchData((data) => {
      callback(data); // Asynchrone
    });
  }
}

Parfois sync, parfois async = comportement imprévisible.

✅ Toujours cohérent (async) :

function alwaysAsync(callback) {
  if (cache) {
    // Forcer async même si donnée en cache
    process.nextTick(() => callback(cache));
    // ou setTimeout(() => callback(cache), 0);
  } else {
    fetchData(callback);
  }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Créez une fonction retry avec callbacks

A
function retryOperation(operation, maxRetries, callback) {
  let attempts = 0;

  function attempt() {
    attempts++;

    operation((err, result) => {
      if (err && attempts < maxRetries) {
        console.log(`Tentative ${attempts} échouée, réessai...`);
        attempt();
      } else {
        callback(err, result);
      }
    });
  }

  attempt();
}

// Usage
function unreliableOperation(callback) {
  if (Math.random() < 0.7) {
    callback(new Error('Échec aléatoire'));
  } else {
    callback(null, 'Succès!');
  }
}

retryOperation(unreliableOperation, 5, (err, result) => {
  if (err) {
    console.error('Échec final:', err);
  } else {
    console.log('Résultat:', result);
  }
});
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Créez une queue de callbacks

A
class CallbackQueue {
  constructor() {
    this.queue = [];
  }

  add(callback) {
    this.queue.push(callback);
  }

  execute() {
    this.queue.forEach(callback => callback());
    this.queue = []; // Vider la queue
  }
}

// Usage
const queue = new CallbackQueue();

queue.add(() => console.log('1'));
queue.add(() => console.log('2'));
queue.add(() => console.log('3'));

queue.execute(); // '1', '2', '3'
How well did you know this?
1
Not at all
2
3
4
5
Perfectly