Ce este o promisiune în JavaScript?

JavaScript are un singur thread, ceea ce înseamnă că doi biți de script nu pot rula în același timp; trebuie să alerge unul după altul. O promisiune este un obiect care reprezintă finalizarea finală (sau eșecul) unei operații asincrone și valoarea rezultată a acesteia.

var promise = new Promise(function(resolve, reject) {
  // do thing, then…

  if (/* everything worked */) {
    resolve("See, it worked!");
  }
  else {
    reject(Error("It broke"));
  }
});

O promisiune există într-una din aceste stări

  • În așteptare: starea inițială, nici îndeplinită, nici respinsă.
  • Realizată: operațiunea a fost finalizată cu succes.
  • Respins: operațiunea nu a reușit.

Obiectul Promisiunea funcționează ca proxy pentru o valoare care nu este neapărat cunoscută atunci când promisiunea este creată. Vă permite să asociați handlerele cu o eventuală valoare de succes sau motiv de eșec al unei acțiuni asincrone.

Acest lucru permite metodelor asincrone să returneze valori precum metodele sincrone: în loc să returneze imediat valoarea finală, metoda asincronă returnează promisiunea de a furniza valoarea la un moment dat în viitor.

Utilizarea „Atunci” (Promise Chaining)

Pentru a prelua mai multe apeluri asincrone și a le sincroniza unul după celălalt, puteți utiliza înlănțuirea promisiunii. Aceasta permite utilizarea unei valori de la prima promisiune în apeluri ulterioare ulterioare.

Promise.resolve('some')
  .then(function(string) { // <-- This will happen after the above Promise resolves (returning the value 'some')
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        string += 'thing';
        resolve(string);
      }, 1);
    });
  })
  .then(function(string) { // <-- This will happen after the above .then's new Promise resolves
    console.log(string); // <-- Logs 'something' to the console
  });

Promite API

Există 4 metode statice în clasa Promise:

  • Promisiune.rezolvați
  • Promisiune.reject
  • Promiteți.toate
  • Promisiunea.rasa

Promisiunile pot fi legate între ele

Atunci când scrieți Promisiuni pentru a rezolva o anumită problemă, le puteți lega împreună pentru a forma logică.

var add = function(x, y) {
  return new Promise((resolve,reject) => {
    var sum = x + y;
    if (sum) {
      resolve(sum);
    }
    else {
      reject(Error("Could not add the two values!"));
    }
  });
};

var subtract = function(x, y) {
  return new Promise((resolve, reject) => {
    var sum = x - y;
    if (sum) {
      resolve(sum);
    }
    else {
      reject(Error("Could not subtract the two values!"));
    }
  });
};

// Starting promise chain
add(2,2)
  .then((added) => {
    // added = 4
    return subtract(added, 3);
  })
  .then((subtracted) => {
    // subtracted = 1
    return add(subtracted, 5);
  })
  .then((added) => {
    // added = 6
    return added * 2;    
  })
  .then((result) => {
    // result = 12
    console.log("My result is ", result);
  })
  .catch((err) => {
    // If any part of the chain is rejected, print the error message.
    console.log(err);
  });

Acest lucru este util pentru urmărirea unui Programare funcțională paradigmă. Prin crearea de funcții pentru manipularea datelor, le puteți înlănțui pentru a asambla un rezultat final. Dacă în orice moment al lanțului de funcții o valoare este respins lanțul va sări la cel mai apropiat catch() manipulant.

Pentru mai multe informații despre programarea funcțională: Programare funcțională

Generatoare de funcții

În versiunile recente, JavaScript a introdus mai multe modalități de gestionare nativă a promisiunilor. Un astfel de mod este generatorul de funcții. Generatoarele de funcții sunt funcții „pauzabile”. Atunci când sunt folosiți cu Promisiunile, generatorii pot face ca utilizarea să fie mult mai ușor de citit și să pară „sincronă”.

const myFirstGenerator = function* () {
  const one = yield 1;
  const two = yield 2;
  const three = yield 3;

  return 'Finished!';
}

const gen = myFirstGenerator();

Iată primul nostru generator, pe care îl puteți vedea de function* sintaxă. gen variabila pe care am declarat-o nu va rula myFirstGenerator, dar în schimb va „acest generator este gata de utilizare”.

console.log(gen.next());
// Returns { value: 1, done: false }

Când alergăm gen.next() acesta va întrerupe generatorul și va continua. De vreme ce este prima dată când sunăm gen.next() va rula yield 1 și întrerupeți până sunăm gen.next() din nou. Când yield 1 este chemat, ne va reveni la value care a fost cedat și dacă generatorul este sau nu done.

console.log(gen.next());
// Returns { value: 2, done: false }

console.log(gen.next());
// Returns { value: 3, done: false }

console.log(gen.next());
// Returns { value: 'Finished!', done: true }

console.log(gen.next());
// Will throw an error

Pe măsură ce continuăm să sunăm gen.next() va continua pe următoarea yield și pauză de fiecare dată. Odată ce nu mai există yieldStânga, va continua să ruleze restul generatorului, care în acest caz se întoarce pur și simplu 'Finished!'. Dacă suni gen.next() din nou, va genera o eroare pe măsură ce generatorul este terminat.

Acum, imaginați-vă dacă fiecare yield în acest exemplu a fost un Promise, codul în sine ar părea extrem de sincron.

Promise.all (iterabil) este foarte util pentru cereri multiple către surse diferite

Metoda Promise.all (iterabilă) returnează o singură promisiune care se rezolvă atunci când toate promisiunile din argumentul iterabil s-au rezolvat sau când argumentul iterabil nu conține promisiuni. Respinge cu motivul primei promisiuni care respinge.

var promise1 = Promise.resolve(catSource);
var promise2 = Promise.resolve(dogSource);
var promise3 = Promise.resolve(cowSource);

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
});
// expected output: Array ["catData", "dogData", "cowData"]

Mai multe informații despre promisiuni:

  • Cum funcționează efectiv promisiunile JavaScript
  • Cum se implementează promisiunile în JavaScript
  • Cum se utilizează promisiunile în JavaScript
  • Cum se scrie o promisiune JavsScript