异步等待永远等待承诺使用块

时间:2017-12-01 21:17:15

标签: javascript node.js asynchronous promise async-await

调用websocket连接(wss.on)的事件处理程序,调用异步函数sendInitialState()。在那里我调用一个异步函数(getMetadata()),它返回一个Promise,在其中我做了一些异步的东西。我解决了这个承诺,resolve(res)被调用,但是程序仍在等待,即console.log(metadata)永远不会被调用。

wss.on('connection', (ws) => {

    sendInitialState();
});

const sendInitialState = async (ws) => {

    console.log('Sending initial state!');
    const metadata = await getMetadata();
    console.log('metadata:', metadata);
};

const getMetadata = async () => {

    return new Promise((resolve, reject) => {
        MongoClient.connect(url, (err, db) => {
            if (err) {reject(err);}
            else {
              db.collection("meta").findOne({type: 'a'}, (err, res) => {
                if (err) reject(err);
                else {
                    db.close();
                    console.log('Metadata found: ', res);
                    resolve(res);
                }

              });
            }
        }); 
    });

}

我的程序阻止了什么原因?

(我尝试在外部(ws) =>之前添加异步,但结果是相同的)

1 个答案:

答案 0 :(得分:1)

虽然reject()'ing承诺而不是投掷解决了它,但您的代码风格可以改进:

  • 将回调转换为promise时,不需要将该函数声明为async:它只会包含在另一个promise中;
  • 最好是声明函数而不是将函数表达式赋给const;
  • 要减少缩进,模式将为if (err) { return reject(err); }:这样就不需要使用else子句;
  • 我们可能希望重用基于承诺的函数,因此提取通用逻辑会导致更易读的代码;

OP更多地是关于promises而不是async / await,所以这是一个重写版本,具有更小的函数,浅缩进和更多的async / await。



wss.on('connection', (ws) => {
  sendInitialState();
});

async function sendInitialState(ws) {
  console.log('Sending initial state!');
  const metadata = await getMetadata();
  console.log('metadata:', metadata);
}

function connect(url) {
  return new Promise((resolve, reject) => {
    MongoClient.connect(url, (err, db) => {
      if (err) {
        return reject(err);
      }
      resolve(db);
    });
  });
}

function findOne(db, collectionName, object) {
  return new Promise((resolve, reject) => {
    db.collection(collectionName).findOne(object, (err, res) => {
      if (err) {
        return reject(err);
      }
      console.log('Metadata found: ', res);
      resolve(res);
    });
  });
}

async function getMetadata() {
  const db = await connect(url);
  const res = await findOne(db, 'meta', {
    type: 'a'
  });
  db.close();
  console.log('Metadata found: ', res);
  return res;
}