推送后数组保持为空

Posted

技术标签:

【中文标题】推送后数组保持为空【英文标题】: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 我应该如何编写代码? 【参考方案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([]);

【讨论】:

没用,还是空的!

以上是关于推送后数组保持为空的主要内容,如果未能解决你的问题,请参考以下文章

1.合并两个数组,并保持仍然有序。2.删除合并后数组中的重复元素

forEach 中的推送对象在地图外观结束时为空 [重复]

Swift 4 完成处理程序:数组保持为空

在承诺中使用 Array.push 时,数组保持为空

无需推送数组的表单验证

异步后如何使全局数组不为空