社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Redis

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

Timothy Vogel • 5 年前 • 1786 次点击  

我读到了 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
 
1786 次点击  
文章 [ 4 ]  |  最新文章 5 年前
akc42
Reply   •   1 楼
akc42    9 年前

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    5 年前

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

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

我看了一下说明书,发现了以下信息。简而言之 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    9 年前

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

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