Aller au contenu

1NSI: Créer ses propres Promesses personnelles en JS⚓︎

Les fonctions javascript new Promise() (etc..) permettant cela ont vu le jour avec ES6 / ES2015 / ECMA2015. Nous avons vu précédemment comment utiliser des fonctions asynchrones déjà existantes, péalablement crées par le javascript.
Mais comment créer nos propres fonctions asynchrones qui renvoient nos propres Promesses personnelles ?

On se place donc ici, dans la situation où vous êtes un développeur de librairie/bibliothèque Javascript, et vous souhaitez créer une API disponible aux autres développeurs.

Rappel sur setTimeout()⚓︎

La fonction setTimeout(fonctionAAppelerApres, duree) patiente durant la durée duree (en millisecondes), PUIS appelle/exécute la fonction fonctionAAppelerApres (une callback donc). C'est comme cela qu'on procédait autrefois. Nous allons créer notre propre fonction personnelle, setTimeoutPromise(), équivalente à setTimeout(), qui renvoie une promesse.

Équivalent de setTimeout() avec Promesse Personnelle⚓︎

On souhaite écrire un code qui ressemble à ceci :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const setTimeoutPromise = (duree) => {
    setTimeout(disBonjour, duree)
}

const disBonjour = () => {
    console.log("Bonjour");
}

setTimeoutPromise(1000)
    .then( () => disBonjour() )
    .catch( (err) => console.log(err) )

Pour le moment, on reçoit une erreur TypeError: Cannot read properties of undefined (reading 'then') car aucune promesse n'a été renvoyée. Pour résoudre cette erreur, il faut que notre fonction setTimeoutPromise() renvoie une (nouvelle) Promesse. Pour faire cela, notre fonction setTimeoutPromise() doit renvoyer (une instance de) la classe javascript new Promise(). De plus (insuffisant à ce stade), lorsque l'on crée une promesse, on doit également dire que faire :

  • en cas de résolution de la promesse
  • en cas de d'erreur rencontrée lors de la tentative de résolution de la promesse**

Nous allons créer une fonction gererLaPromesse(resolve, reject) qui sera chargée de gérer la promesse. Cette fonction gererLaPromesse devra être passée lors de la création de la nouvelle Promesse.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const setTimeoutPromise = (duree) => {
    const gererLaPromesse(resolve, reject) {
        // logique générale à inventer
        // cette fonction doit appeler, au bon moment :
        // * La fonction 'resolve()' pour signaler que, dans ce cas,
        //   la promesse est considérée résolue/'fulfilled'
        // * La fonction 'reject()' pour signaler que, dans ce cas,
        //   la promesse est considérée comme à rejeter/erreur/reject. 
    }
    return new Promise(gererLaPromesse)
}

De plus, en pratique, le plus souvent, on ne se fatiguera même pas à nommer la fonction gererLaPromesse(resolve, reject), on utilisera donc plutôt la syntaxe :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const setTimeoutPromise = (duree) => {
    return new Promise( (resolve, reject) => {
        // logique générale à inventer
        // cette fonction doit appeler, au bon moment :
        // * La fonction 'resolve()' pour signaler que, dans ce cas,
        //   la promesse est considérée résolue/'fulfilled'
        // * La fonction 'reject()' pour signaler que, dans ce cas,
        //   la promesse est considérée comme à rejeter/erreur/reject. 
    } )
}

Exp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const setTimeoutPromise = (duree) => {
    return new Promise( (resolve, reject) => {
        if (isNaN(duree)) { // Si duree n'est pas un nombre
            return reject(new Error('duree doit être un nombre')) // rejet de la promesse
        } // sinon ..
        setTimeout(resolve, duree)  // appelle la fonction 'resolve',
                                    // apres 'duree' millisecondes,
                                    // càd résoud la promesse ..
    } )
}

setTimeoutPromise(1000)
    .then( () => console.log("Bonjour") )
    .catch( (err) => console.log(err) )