2016-02-09 30 views
30

Ho letto che le funzioni asincrone contrassegnate dalla parola chiave async restituiscono implicitamente una promessa:async/await restituisce implicitamente la promessa?

async function getVal(){ 
return await doSomethingAync(); 
} 

var ret = getVal(); 
console.log(ret); 

ma che non è coerente ... assumendo doSomethingAsync() restituisce una promessa, e la parola chiave await restituirà il valore dalla promessa, non è la promessa, ma la mia funzione getVal dovrebbe restituire tale valore, non una promessa implicita,.

Quindi, qual è esattamente il caso? Le funzioni contrassegnate dalla parola chiave async restituiscono implicitamente promesse o controlliamo ciò che restituiscono?

Forse se non restituiamo esplicitamente qualcosa, implicitamente restituiscono una promessa ...?

Per essere più chiari, v'è una differenza tra il sopra e

function doSomethingAync(charlie) { 
    return new Promise(function (resolve) { 
     setTimeout(function() { 
      resolve(charlie || 'yikes'); 
     }, 100); 
    }) 
} 

async function getVal(){ 
    var val = await doSomethingAync(); // val is not a promise 
    console.log(val); // logs 'yikes' or whatever 
    return val; // but this returns a promise 
} 

var ret = getVal(); 
console.log(ret); //logs a promise 

Nella mia riassunto il comportamento è infatti incompatibile con istruzioni return tradizionali. Sembra che quando si restituisce esplicitamente un valore di non promessa da una funzione async, lo imporrà in una promessa. Non ho grossi problemi con esso, ma sfugge al normale JS.

+0

Cosa mostra 'console.log'? – Barmar

+0

è il valore trasmesso dalla funzione di risoluzione promessa, non la promessa stessa –

+0

Forse attende di scartare il risultato della promessa. –

risposta

34

Il valore restituito sarà sempre una promessa. Se non si restituisce esplicitamente una promessa, il valore restituito verrà automaticamente incluso in una promessa.

async function increment(num) { 
    return num + 1; 
} 

// Even though you returned a number, the value is 
// automatically wrapped in a promise, so we call 
// `then` on it to access the returned value. 
// 
// Logs: 4 
increment(3).then(num => console.log(num)); 

Stessa cosa anche se c'è un await.

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

async function incrementTwice(num) { 
    const numPlus1 = await defer(() => num + 1); 
    return numPlus1 + 1; 
} 

// Logs: 5 
incrementTwice(3).then(num => console.log(num)); 

Promises auto-unwrap, quindi se non torna una promessa per un valore da all'interno di una funzione async, si riceverà una promessa per il valore (non una promessa per una promessa per il valore).

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

async function increment(num) { 
    // It doesn't matter whether you put an `await` here. 
    return defer(() => num + 1); 
} 

// Logs: 4 
increment(3).then(num => console.log(num)); 

Nella mia sinossi il comportamento è infatti in contrasto con tradizionali istruzioni return. Sembra che quando si restituisce esplicitamente un valore di non promessa da una funzione asincrona, esso lo imporrà in una promessa . Non ho grossi problemi con esso, ma sfugge al normale JS.

ES6 ha funzioni che non restituiscono esattamente lo stesso valore di return. Queste funzioni sono chiamate generatori.

function* foo() { 
    return 'test'; 
} 

// Logs an object. 
console.log(foo()); 

// Logs 'test'. 
console.log(foo().next().value); 
+0

"il valore restituito verrà automaticamente incluso in una promessa" con il metodo statico Promise.resolve, ad esempio, se l'istruzione di ritorno di una funzione asincrona è - restituisce x; diventa implicitamente - return Promise.resolve (x); – adnan2nd

0

async non restituisce la promessa, la parola chiave di attesa attende la risoluzione della promessa. asincrona è una funzione generatore migliorato e attendere funziona un po 'come resa

Penso che la sintassi (non sono sicuro al 100%) è

async function* getVal() {...}

funzioni del generatore ES2016 funzionano un po' come questo.Ho fatto un gestore di database basato in cima noiosa che si programma come questo

db.exec(function*(connection) { 
    if (params.passwd1 === '') { 
    let sql = 'UPDATE People SET UserName = @username WHERE ClinicianID = @clinicianid'; 
    let request = connection.request(sql); 
    request.addParameter('username',db.TYPES.VarChar,params.username); 
    request.addParameter('clinicianid',db.TYPES.Int,uid); 
    yield connection.execSql(); 
    } else { 
    if (!/^\S{4,}$/.test(params.passwd1)) { 
     response.end(JSON.stringify(
     {status: false, passwd1: false,passwd2: true} 
    )); 
     return; 
    } 
    let request = connection.request('SetPassword'); 
    request.addParameter('userID',db.TYPES.Int,uid); 
    request.addParameter('username',db.TYPES.NVarChar,params.username); 
    request.addParameter('password',db.TYPES.VarChar,params.passwd1); 
    yield connection.callProcedure(); 
    } 
    response.end(JSON.stringify({status: true})); 

}).catch(err => { 
    logger('database',err.message); 
    response.end(JSON.stringify({status: false,passwd1: false,passwd2: false})); 
}); 

Notate come ho appena programmare come sincrono normale particolarmente a

yield connection.execSql e al yield connection.callProcedure

Il db.exec la funzione è un generatore basato su Promise abbastanza tipico

exec(generator) { 
    var self = this; 
    var it; 
    return new Promise((accept,reject) => { 
    var myConnection; 
    var onResult = lastPromiseResult => { 
     var obj = it.next(lastPromiseResult); 
     if (!obj.done) { 
     obj.value.then(onResult,reject); 
     } else { 
     if (myConnection) { 
      myConnection.release(); 
     } 
     accept(obj.value); 
     } 
    }; 
    self._connection().then(connection => { 
     myConnection = connection; 
     it = generator(connection); //This passes it into the generator 
     onResult(); //starts the generator 
    }).catch(error => { 
     reject(error); 
    }); 
    }); 
} 
+2

"* async è una funzione di generatore potenziata *" - no, in realtà non lo è. – Bergi

6

Ho dato un'occhiata alle specifiche e ho trovato le seguenti informazioni. La versione breve è quella di un desugars async function per un generatore che produce Promise s. Quindi, sì, le funzioni asincrone restituiscono le promesse.

Secondo il tc39 spec, il seguente è vera:

async function <name>?<argumentlist><body> 

Desugars a:

function <name>?<argumentlist>{ return spawn(function*() <body>, this); } 

Dove spawn "è una chiamata al seguente algoritmo":

function spawn(genF, self) { 
    return new Promise(function(resolve, reject) { 
     var gen = genF.call(self); 
     function step(nextF) { 
      var next; 
      try { 
       next = nextF(); 
      } catch(e) { 
       // finished with failure, reject the promise 
       reject(e); 
       return; 
      } 
      if(next.done) { 
       // finished with success, resolve the promise 
       resolve(next.value); 
       return; 
      } 
      // not finished, chain off the yielded promise and `step` again 
      Promise.resolve(next.value).then(function(v) { 
       step(function() { return gen.next(v); }); 
      }, function(e) { 
       step(function() { return gen.throw(e); }); 
      }); 
     } 
     step(function() { return gen.next(undefined); }); 
    }); 
} 
Problemi correlati