asynchronous/等待隐式返回诺言?

我读过由async关键字标记的asynchronous函数隐含地返回一个promise:

 async function getVal(){ return await doSomethingAync(); } var ret = getVal(); console.log(ret); 

但是这不是一致的…假设doSomethingAsync()返回一个promise,并且await关键字将从promise中返回值,而不是promise itsef,那么我的getVal函数应该返回这个值,而不是一个隐含的承诺。

那么究竟是什么情况呢? 由async关键字标记的函数隐含地返回promise,还是我们控制返回的内容?

也许如果我们不明确地回报一些东西,那么他们就会隐含地回报一个承诺。

更清楚的是,上面和之间有区别

 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 

在我的大纲中,这种行为确实与传统的返回语句不一致。 看来,当你明确地从一个async函数返回一个非promise的值的时候,它会强制把它包装在一个promise中。 我没有什么大问题,但它确实违背了正常的JS。

       

网上收集的解决方案 "asynchronous/等待隐式返回诺言?"

返回值将永远是一个承诺。 如果您没有明确地返回承诺,则您返回的值将自动包含在承诺中。

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

同样的事情,即使有一个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)); 

承诺自动解包,所以如果你确实在async函数中返回一个值的承诺,你将会得到一个值的承诺(而不是对承诺的承诺)。

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

在我的大纲中,这个行为确实与传统的return语句不一致。 看来,当你明确地从一个asynchronous函数返回一个非promise的值的时候,它会强制把它包装在一个promise中。 我没有什么大问题,但它确实违背了正常的JS。

ES6的function不会返回与返回完全相同的值。 这些函数被称为生成器。

 function* foo() { return 'test'; } // Logs an object. console.log(foo()); // Logs 'test'. console.log(foo().next().value); 

我看了一下规格,发现了以下信息。 简短的版本是一个async function desugars发生器产生Promise s。 所以, 是的,asynchronous函数返回的承诺

根据tc39规范 ,以下是正确的:

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

Desugars到:

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

凡“ spawn ”是对以下algorithm的调用“:

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

async不返回promise,await关键字等待promise的parsing。 asynchronous是一个增强的发生器function,并等待有点像收益

我认为语法(我不是100%肯定)是

async function* getVal() {...}

ES2016发生器function有点像这样。 我已经做了一个基于繁琐的数据库处理程序,你这样编程

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

注意我怎么编程它像正常的同步,特别是在

yield connection.execSql并在yield connection.callProcedure

db.exec函数是一个相当典型的基于Promise的生成器

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