Cosa significa quindi la funzione () in JavaScript?


Risposte:


349

Il modo tradizionale di gestire le chiamate asincrone in JavaScript è stato con i callback. Supponiamo che abbiamo dovuto effettuare tre chiamate al server, una dopo l'altra, per configurare la nostra applicazione. Con i callback, il codice potrebbe essere simile al seguente (supponendo una funzione xhrGET per effettuare la chiamata al server):

// Fetch some server configuration
    xhrGET('/api/server-config', function(config) {
        // Fetch the user information, if he's logged in
        xhrGET('/api/' + config.USER_END_POINT, function(user) {
            // Fetch the items for the user
            xhrGET('/api/' + user.id + '/items', function(items) {
                // Actually display the items here
            });
        });
    });

In questo esempio, prima recuperiamo la configurazione del server. Quindi, in base a ciò, recuperiamo informazioni sull'utente corrente e infine otteniamo l'elenco degli elementi per l'utente corrente. Ogni chiamata xhrGET utilizza una funzione di richiamata che viene eseguita quando il server risponde.

Ora ovviamente più livelli di annidamento abbiamo, più difficile è leggere, eseguire il debug, mantenere, aggiornare e sostanzialmente lavorare con il codice. Questo è generalmente noto come l'inferno di callback. Inoltre, se abbiamo bisogno di gestire gli errori, dobbiamo eventualmente passare un'altra funzione a ciascuna chiamata xhrGET per dirgli cosa deve fare in caso di errore. Se volessimo avere un solo gestore di errori comune, questo non è possibile.

L'API Promise è stata progettata per risolvere questo problema di nidificazione e il problema della gestione degli errori.

L'API Promise propone quanto segue:

  1. Ogni attività asincrona restituirà un promiseoggetto.
  2. Ogni promiseoggetto avrà una thenfunzione che può accettare due argomenti, un success gestore e un errorgestore.
  3. L'esito positivo o il gestore degli errori nella thenfunzione verrà chiamato una sola volta , al termine dell'attività asincrona.
  4. La thenfunzione restituirà anche a promise, per consentire il concatenamento di più chiamate.
  5. Ogni gestore (esito positivo o errore) può restituire a value, che verrà passato alla funzione successiva come a argument, nella catena di promises.
  6. Se un gestore restituisce un promise(effettua un'altra richiesta asincrona), il gestore successivo (esito positivo o errore) verrà chiamato solo al termine della richiesta.

Quindi il codice di esempio precedente potrebbe tradursi in qualcosa di simile al seguente, usando promesse e il $httpservizio (in AngularJs):

$http.get('/api/server-config').then(
    function(configResponse) {
        return $http.get('/api/' + configResponse.data.USER_END_POINT);
    }
).then(
    function(userResponse) {
        return $http.get('/api/' + userResponse.data.id + '/items');
    }
).then(
    function(itemResponse) {
        // Display items here
    }, 
    function(error) {
        // Common error handling
    }
);

Propagare successo ed errore

Il concatenamento delle promesse è una tecnica molto potente che ci consente di ottenere molte funzionalità, come fare in modo che un servizio faccia una chiamata al server, esegua un po 'di postelaborazione dei dati e quindi restituisca i dati elaborati al controller. Ma quando lavoriamo con le promisecatene, ci sono alcune cose che dobbiamo tenere a mente.

Considera la seguente ipotetica promisecatena con tre promesse, P1, P2 e P3. Ognuno promiseha un gestore di successo e un gestore di errori, quindi S1 ​​ed E1 per P1, S2 ed E2 per P2 e S3 ed E3 per P3:

xhrCall()
  .then(S1, E1) //P1
  .then(S2, E2) //P2
  .then(S3, E3) //P3

Nel normale flusso di cose, dove non ci sono errori, l'applicazione scorre attraverso S1, S2 e infine S3. Ma nella vita reale, le cose non sono mai così lisce. P1 potrebbe riscontrare un errore o P2 potrebbe riscontrare un errore, innescando E1 o E2.

Considera i seguenti casi:

• Riceviamo una risposta corretta dal server in P1, ma i dati restituiti non sono corretti o non ci sono dati disponibili sul server (pensate ad array vuoto). In tal caso, per la prossima promessa P2, dovrebbe attivare il gestore degli errori E2.

• Riceviamo un errore per promessa P2, innescando E2. Ma all'interno del gestore, abbiamo i dati dalla cache, assicurando che l'applicazione possa essere caricata normalmente. In tal caso, potremmo voler garantire che dopo E2 venga chiamato S3.

Quindi ogni volta che scriviamo un gestore di errori o di successo, dobbiamo effettuare una chiamata: data la nostra attuale funzione, questa promessa è un successo o un fallimento per il prossimo gestore nella catena di promesse?

Se vogliamo attivare il gestore del successo per la prossima promessa nella catena, possiamo semplicemente restituire un valore dal gestore del successo o dell'errore

Se, d'altra parte, vogliamo innescare il gestore degli errori per la prossima promessa nella catena, possiamo farlo usando un deferredoggetto e chiamando il suo reject()metodo

Ora che cos'è l'oggetto differito?

Gli oggetti differiti in jQuery rappresentano un'unità di lavoro che verrà completata in seguito, in genere in modo asincrono. Una volta completata l'unità di lavoro, l' deferredoggetto può essere impostato su risolto o fallito.

Un deferredoggetto contiene un promiseoggetto. Tramite l' promiseoggetto è possibile specificare cosa deve succedere al completamento dell'unità di lavoro. Puoi farlo impostando le funzioni di callback promisesull'oggetto.

Oggetti differiti in Jquery: https://api.jquery.com/jquery.deferred/

Oggetti differiti in AngularJs: https://docs.angularjs.org/api/ng/service/ $ q


3
Molto ben scritto Questo mi ha aiutato a inchiodare le promesse.
Ju66ernaut,

Il gestore degli errori, il secondo parametro, è sempre facoltativo?
1,21 gigawatt

Questa è di gran lunga la migliore risposta che ho visto finora!
Imam Bux,

78

la funzione then () è correlata alle "promesse Javascript" utilizzate in alcune librerie o framework come jQuery o AngularJS.

Una promessa è un modello per la gestione di operazioni asincrone. La promessa consente di chiamare un metodo chiamato "then" che consente di specificare le funzioni da utilizzare come callback.

Per ulteriori informazioni, consultare: http://wildermuth.com/2013/8/3/JavaScript_Promises

E per le promesse angolari: http://liamkaufman.com/blog/2013/09/09/using-angularjs-promises/


4
quindi è come un callback che viene eseguito al termine dell'attività? In che modo è diverso
Muhammad Umer del

3
le promesse JavaScript nell'altro commento dicono A promise can only succeed or fail onceIf a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called
:,

Inoltre, le pepite Promise spiegano come usare promisee cosa si farebbecallback
Xiao

Nella prima pagina, ci sono pezzi di codice mancanti (grandi spazi bianchi). La maggior parte delle persone penserà di ispezionare l'elemento e troverà sotto gli URL del violino. Questo messaggio è per il resto - i violini funzionano ancora;)
DanteTheSmith

1
@MuhammadUmer: leggere questo stackoverflow.com/a/31453579/1350476 (risposta da Sid)
SharpCoder

32

Per quanto ne sappia, non esiste un then()metodo integrato in javascript(al momento della stesura di questo documento).

Sembra che qualunque cosa doSome("task")stia tornando ha un metodo chiamato then.

Se si registra il risultato di ritorno doSome()sulla console, si dovrebbe essere in grado di vedere le proprietà di ciò che è stato restituito.

console.log( myObj.doSome("task") ); // Expand the returned object in the
                                     //   console to see its properties.

AGGIORNAMENTO (a partire da ECMAScript6) : -

La .then()funzione è stata inclusa in javascript puro.

Dalla documentazione di Mozilla qui ,

Il metodo then () restituisce una promessa. Sono necessari due argomenti: funzioni di callback per i casi di successo e fallimento della Promessa.

L'oggetto Promise, a sua volta, è definito come

L'oggetto Promise viene utilizzato per calcoli differiti e asincroni. Una promessa rappresenta un'operazione che non è stata ancora completata, ma è prevista in futuro.

Cioè, Promiseagisce come un segnaposto per un valore che non è stato ancora calcolato, ma che sarà risolto in futuro. E la .then()funzione viene utilizzata per associare le funzioni da invocare sulla Promessa quando viene risolta, sia come successo che come fallimento.


12
.thenAllora non c'era un built-in , ma le promesse native stanno arrivando ora in ES6: html5rocks.com/en/tutorials/es6/promises
janfoeh

grazie per questa risposta, mi aspettavo un bel richiamo promettente ma si è rivelata una vera funzione chiamata "allora" che è stata restituita.
spartikus,

15

Ecco una cosa che ho fatto per me stesso per chiarire come funzionano le cose. Immagino che anche altri possano trovare utile questo esempio concreto:

doit().then(function() { log('Now finally done!') });
log('---- But notice where this ends up!');

// For pedagogical reasons I originally wrote the following doit()-function so that 
// it was clear that it is a promise. That way wasn't really a normal way to do 
// it though, and therefore Slikts edited my answer. I therefore now want to remind 
// you here that the return value of the following function is a promise, because 
// it is an async function (every async function returns a promise). 
async function doit() {
  log('Calling someTimeConsumingThing');
  await someTimeConsumingThing();
  log('Ready with someTimeConsumingThing');
}

function someTimeConsumingThing() {
  return new Promise(function(resolve,reject) {
    setTimeout(resolve, 2000);
  })
}

function log(txt) {
  document.getElementById('msg').innerHTML += txt + '<br>'
}
<div id='msg'></div>


5

Ecco un piccolo JS_Fiddle.

quindi è uno stack di callback del metodo che è disponibile dopo che una promessa è stata risolta fa parte della libreria come jQuery ma ora è disponibile in JavaScript nativo e di seguito è la spiegazione di dettaglio come funziona

Puoi fare una Promessa in JavaScript nativo: proprio come ci sono promesse in jQuery, Ogni promessa può essere accatastata e quindi può essere chiamata con Risolvi e Rifiuta richiamate, Ecco come puoi concatenare le chiamate asincrone.

Ho modificato e modificato i documenti MSDN sullo stato di carica della batteria.

Quello che fa è provare a scoprire se il laptop o il dispositivo dell'utente sta caricando la batteria. poi viene chiamato e puoi fare il tuo lavoro dopo il successo.

navigator
    .getBattery()
    .then(function(battery) {
       var charging = battery.charging;
       alert(charging);
    })
    .then(function(){alert("YeoMan : SINGH is King !!");});

Un altro esempio es6

function fetchAsync (url, timeout, onData, onError) {
    
}
let fetchPromised = (url, timeout) => {
    return new Promise((resolve, reject) => {
        fetchAsync(url, timeout, resolve, reject)
    })
}
Promise.all([
    fetchPromised("http://backend/foo.txt", 500),
    fetchPromised("http://backend/bar.txt", 500),
    fetchPromised("http://backend/baz.txt", 500)
]).then((data) => {
    let [ foo, bar, baz ] = data
    console.log(`success: foo=${foo} bar=${bar} baz=${baz}`)
}, (err) => {
    console.log(`error: ${err}`)
})

Definizione :: then è un metodo utilizzato per risolvere i callback asincroni

questo è introdotto in ES6

Trova la documentazione corretta qui Promesse Es6


La tua risposta in realtà non risponde alla domanda. Fornisce solo un esempio dell'utilizzo dell'API senza spiegare da dove thenproviene e come funziona. È necessario migliorare la risposta per fornire tali dettagli.
Didier L

@TarandeepSingh - in primo luogo poi istruzione in cui si avverte lo stato della batteria, non viene restituito alcun oggetto promessa. Allora a che serve il secondo allora
Mohit Jain,

@MohitJain Mostra che puoi fare più callback anche se non hai nuove promesse. Da allora, le chiamate multiple potrebbero anche essere fatte con Promise.all.
Tarandeep Singh,

Cosa intendi con " metodo callback stack "?
Bergi,

4

Sospetto che doSome restituisca questo, che è myObj, che ha anche un metodo allora. Concatenamento con metodo standard ...

se doSome non lo restituisce, essendo l'oggetto su cui è stato eseguito doSome, ti assicuro che sta restituendo un oggetto con un metodo then ...

come sottolinea @patrick, non esiste nessun () per js standard


1
Ho il sospetto che doSome restituisca questo - niente rinforza / giustifica tali sospensioni
Genèse

1

doSome ("task") deve restituire un oggetto promise e quella promessa ha sempre una funzione then. Quindi il tuo codice è proprio così

promise.then(function(env) {
    // logic
}); 

e sai che questa è solo una normale chiamata alla funzione membro.


1

.then restituisce una promessa nella funzione asincrona.

Un buon esempio sarebbe:

var doSome = new Promise(function(resolve, reject){
    resolve('I am doing something');
});

doSome.then(function(value){
    console.log(value);
});

Per aggiungere un'altra logica, puoi anche aggiungere la reject('I am the rejected param')chiamata alla funzione e console.log.


0

In questo caso then()è un metodo di classe dell'oggetto restituito dal doSome()metodo.



0

Un altro esempio:

new Promise(function(ok) {
   ok( 
      /* myFunc1(param1, param2, ..) */
   )
}).then(function(){
     /* myFunc1 succeed */
     /* Launch something else */
     /* console.log(whateverparam1) */
     /* myFunc2(whateverparam1, otherparam, ..) */
}).then(function(){
     /* myFunc2 succeed */
     /* Launch something else */
     /* myFunc3(whatever38, ..) */
})

La stessa logica usando la scorciatoia delle funzioni freccia:

new Promise((ok) =>
   ok( 
      /* myFunc1(param1, param2, ..) */
)).then(() =>
     /* myFunc1 succeed */
     /* Launch something else */
     /* Only ONE call or statment can be made inside arrow functions */
     /* For example, using console.log here will break everything */
     /* myFunc2(whateverparam1, otherparam, ..) */
).then(() =>
     /* myFunc2 succeed */
     /* Launch something else */
     /* Only ONE call or statment can be made inside arrow functions */
     /* For example, using console.log here will break everything */
     /* myFunc3(whatever38, ..) */
)


-4

Sono in ritardo di circa 8 anni, beh ... comunque, non so davvero cosa faccia allora () ma forse MDN potrebbe avere una risposta. In realtà, potrei davvero capirlo un po 'di più.

Questo ti mostrerà tutte le informazioni (si spera) di cui hai bisogno. A meno che qualcuno non abbia già pubblicato questo link. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

Il formato è promise.prototype.then () La promessa e il prototipo sono una specie di variabili simili ma non come variabili in javascript, intendo come altre cose vanno lì come navigator.getBattery (). Then () dove questo esiste realmente ma è usato a malapena sul Web, questo mostra gli stati della batteria del dispositivo, ulteriori informazioni e altro su MDN se sei curioso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.