【问题标题】:Array remains empty after push推送后数组保持为空
【发布时间】:2019-06-13 13:33:09
【问题描述】:

我声明了一个数组,但是当我将元素推入其中时,它仍然是空的。这是我的代码:

  var catsObjectId = new Array();
  var data = new Array();
  Recipe.find((err,doc3)=> {
    data = doc3;
    for (var i = 0; i < data.length; i++) {
      catsObjectId.push([]);
      data[i]['categories'].forEach((item, index) => {
        Recipecat.findOne({_id: item}, (err,result)=> {
          item = result.name;
          catsObjectId.push(item);
        });
      })
    }
    console.log(catsObjectId);
  });

这是配方架构:

var recipeSchema = Schema({
  categories: [{
    type: Schema.Types.ObjectId,
    ref: 'RecipeCat',
  }]
});

这是 Recipecat 架构:

var recipecatSchema = new Schema({
    name: {
        type: String,
        required: true
    }
});

我想用他们的名字替换 recipeCats 的 objectIds。

当我记录“catsObjectId”时,它显示一个空数组。

似乎是什么问题?

提前致谢!

【问题讨论】:

  • .find().findOne() 是异步的
  • @Andreas 我应该如何编写代码?

标签: javascript arrays node.js express


【解决方案1】:

(我知道这个问题有点老了,但如果您仍然需要帮助)

那是因为您正在推送到callback 之外的arrayJavaScriptasync 性质。

这里简单解释一下为什么它是空的

var catsObjectId = new Array();
var data = new Array();

Recipe.find((err,doc3)=> {
  // say execution 1
  for (var i = 0; i < data.length; i++) {
    catsObjectId.push([]);
    data[i]['categories'].forEach((item, index) => {
      // say execution 2
      Recipecat.findOne({_id: item}, (err,result)=> {
        item = result.name;
        catsObjectId.push(item);
      });
    })
  }
  // say execution 3
  console.log(catsObjectId);
});

首先执行execution 1。在这个forEach 中迭代每个项目并触发execution 2。然后继续执行execution 3

问题是execution 2 是异步的,并且值在future 中的某个时间返回。这个未来是在excution 3 被执行之后。当Recipecat.findOne 完成执行时,将调用then(result.. 中的callback。但是console.log(catsObjectId) 已经被执行,而catsObjectId 在执行时是空的。

您应该在回调.then((data) =&gt; // use data here) 中使用catsObjectId 或使用async/await 使其成为sync 喜欢。

注意await仅在async函数内部有效

async function getSomeNames() {
  try {
    const data = await Recipe.find();
    // docs is an array of promises
    const docs = data.map((item, index) => {
      Recipecat.findOne({_id: item})
    });
    // items is an array of documents returned by findOne
    const items = await Promise.all(docs);
    // now you can map and get the names
    const names = items.map(item => item.name);
  } catch (e) {
    // handle error
    console.error(e);
  }
}
getSomeNames()

【讨论】:

    【解决方案2】:

    您必须使用 Promise 来控制您的代码。试试下面的代码并告诉我是否存在错误。

    Recipe.find().then(doc3 => {
        data = doc3;
        for (var i = 0; i < data.length; i++) {
          data[i]['categories'].forEach((item, index) => {
            Recipecat.findOne({_id: item}).then(result => {
              item = result.name;
              catsObjectId.push(item);
            });
          })
        }
        console.log(catsObjectId);
      })
      .catch(err => {
          console.log(err);
      });
    

    【讨论】:

    • 没用,还是空的!
    • 每次推送后尝试“console.log”查看发生了什么。例如试试这个:catsObjectId.push(item);控制台.log(项目); console.log(catsObjectId);
    • 'console.log' 推送后工作正常,但外面显示为空。
    【解决方案3】:

    每次通过 for 循环时都会推送一个空数组。尝试删除此行。

    catsObjectId.push([]);
    

    【讨论】:

    • 没用,还是空的!
    猜你喜欢
    • 2021-12-26
    • 2017-08-16
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 2013-03-06
    • 2021-10-13
    • 1970-01-01
    相关资源
    最近更新 更多