Promesses

Pourquoi

  • Gérer plus facilement des traitements asynchrones
  • Rendre le traitement asynchrone imbriqué vertical
  • Retourner des valeurs futures

Avant

setTimeout(function() {
  console.log("Après 1 seconde.");
  setTimeout(function() {
    console.log("Après 1 seconde.");
    setTimeout(function() {
      console.log("Après 1 seconde.");
      setTimeout(function() {
        console.log("Après 1 seconde.");
      }, 1000);
    }, 1000);
  }, 1000);
}, 1000);

Après

function sleep(seconds) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve();
    }, 1000 * seconds);
  });
}

sleep(1).then(function() {
  return sleep(1);
  console.log("Après 1 seconde.");
}).then(function() {
  console.log("Après 1 seconde.");
  return sleep(1);
}).then(function() {
  console.log("Après 1 seconde.");
  return sleep(1);
}).then(function() {
  console.log("Après 1 seconde.");
});

Promise

  • Créer une valeur asynchrone
  • Peut résoudre une valeur
  • Peut échouer

Utilisation

new Promise(function(resolve) {
  resolve("OK");
});

Utilisation

new Promise(function(resolve, reject) {
  reject(new Error("Une erreur est survenue"));
});

Utilisation

new Promise(function(resolve) {
  setTimeout(function() {
    resolve();
  }, 1000);
});

État

pending

const promise = new Promise(function(resolve) {
  setTimeout(function() {
    resolve();
  }, 100000000);
});

console.log(promise);
// Promise { <pending> }

fulfilled

const promise = new Promise(function(resolve) {
  resolve(123);
});

console.log(promise);
// Promise { 123 }

rejected

const promise = new Promise(function(resolve, reject) {
  reject(new Error("Une erreur est survenue"));
});

console.log(promise);
// Promise { Error: Une erreur est survenue }

Promise.prototype.then

Utilisation

function success(value) {
  return new Promise(function(resolve) {
    resolve(value);
  });
}

success(123).then(function(value) {
  console.log(value);
  // 123
});

Promise.prototype.catch

Utilisation

function failure(reason) {
  return new Promise(function(resolve, reject) {
    reject(new Error(reason));
  });
}

failure("Pour aucune raison").catch(function(error) {
  if (error instanceof Error) {
    console.error(error.message);
  } else {
    console.error(String(error));
  }
});

Promise.prototype.finally

Utilisation

function maybe(value) {
  return new Promise(function(resolve, reject) {
    if (Math.random() > 0.5) {
      resolve(value);
    } else {
      reject(new Error("Une erreur est survenue"));
    }
  });
}

maybe(123).then(function(value) {
  console.log(value);
}).catch(function(error) {
  if (error instanceof Error) {
    console.error(error.message);
  } else {
    console.error(String(error));
  }
}).finally(function() {
  console.log("Toujours appelé");
});

Promise.resolve

Utilisation

Promise.resolve(123);

// Équivalent

new Promise(function(resolve) {
  resolve(123);
});

Promise.reject

Utilisation

Promise.reject(new Error("Une erreur est survenue"));

// Équivalent

new Promise(function(resolve, reject) {
  reject(new Error("Une erreur est survenue"));
});

Promise.race

Utilisation

function after(seconds, value) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve(value);
    }, 1000 * seconds);
  });
}

Promise.race([
  after(1, "Premier"),
  after(2, "Second"),
  after(3, "Troisième")
]).then(function(value) {
  console.log(value);
  // "Premier"
});

Promise.all

Utilisation

function after(seconds, value) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      resolve(value);
    }, 1000 * seconds);
  });
}

Promise.all([
  after(1, "Premier"),
  after(2, "Second"),
  after(3, "Troisième")
]).then(function(values) {
  for (const value of values) {
    console.log(value);
  }
});

Promise.any

Utilisation

function success(value) {
  return new Promise(function(resolve) {
    resolve(value);
  });
}

function failure(reason) {
  return new Promise(function(resolve, reject) {
    reject(new Error(reason));
  });
}

Promise.any([
  failure("Première erreur"),
  success("Premier message"),
  failure("Deuxième erreur"),
  success("Second message")
]).then(function(value) {
  console.log(value);
}).catch(function(error) {
  if (error instanceof Error) {
    console.error(error.message);
  } else {
    console.error(String(error));
  }
});

Exemples

sleep

function sleep(seconds) {
  return new Promise(function(resolve, reject) {
    if (!Number.isInteger(seconds)) {
      reject(new Error("first argument is not an integer"));
    } else {
      setTimeout(function() {
        resolve();
      }, 1000);
    }
  });
}

sleep(1).then(function() {
  console.log("After one second.");
}).catch(function(error) {
  if (error instanceof Error) {
    console.error(error.message);
  } else {
    console.error(String(error));
  }
});

getElementById

function getElementById(identifier) {
  return new Promise(function(resolve, reject) {
    if (typeof identifier !== "string") {
      reject(new Error("first argument is not a string"));
    } else {
      const element = document.getElementById(identifier);

      if (element instanceof HTMLElement) {
        resolve(element);
      } else {
        reject(new Error("first argument is not a valid identifier"));
      }
    }
  });
}

getElementById("title").then(function(element) {
  element.innerText = "Hello, world!";
}).catch(function(error) {
  if (error instanceof Error) {
    console.error(error.message);
  } else {
    console.error(String(error));
  }
});

fetch

fetch("https://jsonplaceholder.typicode.com/users").then(function(response) {
  if (response.ok) {
    return response.json();
  }

  return Promise.reject(new Error("Bad response from the server"));
}).then(function(users) {
  console.log(users);
}).catch(function(error) {
  if (error instanceof Error) {
    console.error(error.message);
  } else {
    console.error(String(error));
  }
});

fetch avancé

Promise.all([
  fetch("https://jsonplaceholder.typicode.com/users"),
  fetch("https://jsonplaceholder.typicode.com/posts"),
  fetch("https://jsonplaceholder.typicode.com/comments"),
  fetch("https://jsonplaceholder.typicode.com/todos"),
  fetch("https://jsonplaceholder.typicode.com/articles"),
  fetch("https://jsonplaceholder.typicode.com/albums")
]).then(function(entities) {
  for (const entity of entities) {
    console.log(entity);
  }
}).catch(function(error) {
  if (error instanceof Error) {
    console.error(error.message);
  } else {
    console.error(String(error));
  }
});

Promesses

By Amin Nairi