2016-02-09 5 views
30

ich gelesen, dass Asynchron-Funktionen durch das Schlüsselwort ein Versprechen implizit zurückgeben async markiert:Async/wartet implizit zurück Versprechen?

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

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

aber das ist nicht kohärent ist ... vorausgesetzt, doSomethingAsync() ein Versprechen gibt, und das await Schlüsselwort wird der Wert aus dem Versprechen, zurückzukehren, nicht das Versprechen itsef, dann sollte meine getVal Funktion diesen Wert zurückgeben, kein implizites Versprechen.

Also was genau ist der Fall? Versehen Funktionen, die durch das async-Schlüsselwort gekennzeichnet sind, implizit Versprechen oder kontrollieren wir, was sie zurückgeben?

Vielleicht, wenn wir etwas nicht explizit zurückgeben, dann geben sie implizit ein Versprechen ...?

mehr klar zu sein, gibt es einen Unterschied zwischen der oben und

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 

In meinem Synopse das Verhalten mit traditionellen return-Anweisungen in der Tat unvereinbar ist. Es scheint, dass, wenn Sie explizit einen nicht-Versprechen-Wert aus einer async-Funktion zurückgeben, wird es gezwungen, es in eine Zusage umzubrechen. Ich habe kein großes Problem, aber es ist normal JS.

+0

Was wird 'console.log' angezeigt? – Barmar

+0

ist es der Wert, der durch die Versprechensauflösungsfunktion übergeben wird, nicht das Versprechen selbst –

+0

Vielleicht warten, wickelt das Ergebnis vom Versprechen ab. –

Antwort

34

Der Rückgabewert ist immer ein Versprechen. Wenn Sie eine Zusage nicht explizit zurückgeben, wird der von Ihnen zurückgegebene Wert automatisch in eine Zusicherung eingeschlossen.

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)); 

Das Gleiche gilt auch, wenn es eine await gibt.

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, wenn Sie also innerhalb einer async Funktion ein Versprechen für einen Wert kehren, werden Sie ein Versprechen für den Wert (kein Versprechen für ein Versprechen für den Wert) erhalten.

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)); 

In meinem Synopse ist das Verhalten in der Tat nicht mit traditionellen return-Anweisungen. Es scheint, dass, wenn Sie explizit einen nicht versprechen Wert aus einer asynchronen Funktion zurückgeben, es wird es in eine Versprechen zwingen. Ich habe kein großes Problem damit, aber es trotzt normalen JS.

ES6 hat Funktionen, die nicht genau den gleichen Wert wie die return zurückgeben. Diese Funktionen werden Generatoren genannt.

+0

"der Wert, den Sie zurückgeben, wird automatisch in ein Versprechen eingeschlossen" durch die statische Methode Promise.resolve, d. H. Wenn die return-Anweisung einer asynchronen Funktion ist - return x; es wird implizit - return Promise.resolve (x); – adnan2nd

0

async gibt das Versprechen nicht zurück, das await-Schlüsselwort wartet auf die Lösung des Versprechens. async ist eine verbesserte Generatorfunktion und warten funktioniert ein bisschen wie Ausbeute

Ich denke, die Syntax (Ich bin nicht 100% sicher)

async function* getVal() {...}

ES2016 Generator-Funktionen ist ein bisschen wie das funktioniert.Ich habe eine Datenbank-Handler mit Sitz in Top-mühsamer gemacht, die Sie dieses Programm wie

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})); 
}); 

Beachten Sie, wie ich programmieren sie wie normale Synchron besonders bei

yield connection.execSql und bei yield connection.callProcedure

Die db.exec Funktion ist eine ziemlich typische Promise-basierte Generator

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 ist eine erweiterte Generatorfunktion *" - Nein, ist es wirklich nicht. – Bergi

6

Ich habe einen Blick auf die Spezifikation und gefunden die folgende Information. Die kurze Version ist, dass ein async function desugars zu einem Generator, der Promise s liefert. Also, ja, asynchrone Funktionen versprechen Versprechen.

Nach dem tc39 spec, gilt folgendes:

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

Desugars zu:

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

Wo spawn "einen Aufruf an den folgenden Algorithmus ist":

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); }); 
    }); 
}