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。
返回值将永远是一个承诺。 如果您没有明确地返回承诺,则您返回的值将自动包含在承诺中。
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); }); }); }