Py学习  »  Redis

为什么redis.getAsync在nodejs中与async/await一起使用时返回一个挂起的承诺?[副本]

Timothy Vogel • 4 年前 • 1252 次点击  

我读到了 async 关键字隐式返回承诺:

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

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

但这不是连贯的…假设 doSomethingAsync() 返回一个promise,await关键字将从promise返回值,而不是promise itsef,然后返回my getVal函数 应该 返回那个值,而不是一个隐含的承诺。

那么到底是什么情况?async关键字标记的函数是否隐式返回承诺,或者我们是否控制它们返回的内容?

也许如果我们不明确地返回某个东西,那么他们就隐式地返回一个承诺。。。?

更清楚地说,上面和

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

在我的概要中,这种行为确实与传统的返回语句不一致。当您显式地从 异步 函数,它将强制将其包装在一个承诺中。 我没有什么大问题,但它确实违背了正常的JS。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/49717
 
1252 次点击  
文章 [ 4 ]  |  最新文章 4 年前
akc42
Reply   •   1 楼
akc42    8 年前

async不返回promise,await关键字等待promise的解析。async是一个增强的生成器函数,await的工作方式有点像yield

我认为语法(我不是百分之百确定)是

async function* getVal() {...}

ES2016生成器函数的工作方式有点像这样。我已经制作了一个数据库处理程序,它基于您这样编程的繁琐之上

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

exec函数是一个相当典型的基于承诺的生成器

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);
    });
  });
}
mohsen gharivand
Reply   •   2 楼
mohsen gharivand    4 年前

调用函数时,只需在函数前添加await:

var ret = await  getVal();
console.log(ret);
Jon Surrell
Reply   •   3 楼
Jon Surrell    8 年前

我看了一下说明书,发现了以下信息。简而言之 async function 去糖机 Promise 所以, 是的,异步函数返回承诺 .

根据 tc39 spec ,以下是正确的:

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

去糖:

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

在哪里? spawn “是对以下算法的调用”:

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); });
    });
}
Nathan Wall
Reply   •   4 楼
Nathan Wall    8 年前

回报价值永远是一个承诺。如果您没有显式地返回一个承诺,那么您返回的值将自动包装在一个承诺中。

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

在我的大纲中,这种行为确实与传统的 返回语句当您显式返回 异步函数的非承诺值,它将强制将其包装为 答应我。我没什么大问题,但它确实不正常 杰斯。

ES6的函数返回的值与 return . 这些函数称为生成器。

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

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

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