javascript UnhandledPromiseRejectionWarning:TypeError:无法读取未定义的属性“forEach”

Tom*_*awn 5 javascript mongodb

我正在关注来自 mongoDB js API 的代码示例,非常简单的代码示例:

const getAddressFromDB = async () => {
  const MongoClient = require('mongodb').MongoClient;
  const assert = require('assert');

  let res = []
  let num = 0

  // Connection URL
  const url = 'mongodb://localhost:27017';

  // Database Name
  const dbName = 'addr';

  // Use connect method to connect to the server
  MongoClient.connect(url, function(err, client) {
    assert.equal(null, err);
    console.log("Connected correctly to db");

    const db = client.db(dbName);

    findDocuments(db, function(doc) {
      client.close();
      console.log(doc);
      //return doc
      res = doc 
      num = 1
    });
  });

  const findDocuments = function(db, callback) {
    // Get the documents collection
    const collection = db.collection('documents');
    // Find some documents
    collection.find({}).toArray(function(err, docs) {
      assert.equal(err, null);
      //console.log("Found the following records");
      //console.log(docs)
      //docs.forEach(function(element){
      //  address.push(element.address)
      //});
      //res = docs
      callback(docs);
    });
  }


  if(num == 1){
    return res
  }
}

const helper = async() => {
  let addressList = await getAddressFromDB()
  console.log(addressList)
  addressList.forEach(function(element){
    console.log(element)
    console.log("trying "+element.address)
    checkBalanceAndSendTx(element.address,element.privateKey)
  });
}

helper()
Run Code Online (Sandbox Code Playgroud)

我试图从本地主机上的 mongoDB 获取文档,然后将该数组传递给 foreach 循环并执行某些操作,但是,我得到 TypeError: Cannot read property 'forEach' of undefined,命令的输出如下所示:

undefined
    (node:6757) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'forEach' of undefined
        at helper (/home/ubuntu/second/web3-node-tutorial/se.js:298:15)
        at process._tickCallback (internal/process/next_tick.js:68:7)
        at Function.Module.runMain (internal/modules/cjs/loader.js:721:11)
        at startup (internal/bootstrap/node.js:228:19)
        at bootstrapNodeJSCore (internal/bootstrap/node.js:576:3)
    (node:6757) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
    (node:6757) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    Connected correctly to db
    [ { _id: 5b24b4e042ed9c0fed9d1f15,
        address: '0x6FD04070704vvvC35194316a9033e10120',
        privateKey: '0xc0ea45525dd0a04d6a0f8228czxc1807f6550948fde824d60167c37097c3' },
      { _id: 5b24b4e34257170ff8816e2c,
        address: '0x45bCbe21basd830831a2783d620afFF549D5Ce',
        privateKey: '0x520dbee37681a33d8c9180419c121d3c5sdfafde7ed3f750f7fc279f757c423' } ]
Run Code Online (Sandbox Code Playgroud)

有人能指出为什么我在 getAddressFromDB() 中得到未定义的数组吗?我应该从 db 获取我想要的数组,因为我只在 num 为 1 时返回 res。

Pat*_*und 4

当您等待像getAddressFromDB这样的函数时,该函数需要返回一个承诺。在您的代码中,您正在返回undefined,因为您的 return 语句始终在数据库操作的回调执行完成之前执行。添加异步并不会改变这一点。

您可以通过定义 Promise 并返回它来解决此问题,如下所示(请参阅代码中的注释以获取进一步说明):

// don't call require inside your function, it's common
// practice to do that at the beginning of your module
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');

const getAddressFromDB = () => {

    // async functions need to return a promise,
    // so we create one and and wrap everything in it
    return new Promise(resolve => {
        let res = []
        let num = 0

        // Connection URL
        const url = 'mongodb://localhost:27017';

        // Database Name
        const dbName = 'addr';

        // Use connect method to connect to the server
        MongoClient.connect(url, function (err, client) {
            assert.equal(null, err);
            console.log("Connected correctly to db");

            const db = client.db(dbName);

            findDocuments(db, function (doc) {
                client.close();
                console.log(doc);

                // this makes your promise ultimately resolve
                // with the doc from MongoDB
                resolve(doc);
            });
        });

        const findDocuments = function (db, callback) {
            // Get the documents collection
            const collection = db.collection('documents');
            // Find some documents
            collection.find({}).toArray(function (err, docs) {
                assert.equal(err, null);
                callback(docs);
            });
        }
    });
}

const helper = async () => {
    let addressList = await getAddressFromDB()
    console.log(addressList)
    addressList.forEach(function (element) {
        console.log(element)
        console.log("trying " + element.address)
        checkBalanceAndSendTx(element.address, element.privateKey)
    });
}

helper()
Run Code Online (Sandbox Code Playgroud)