我知道这个话题已经被问过很多次了,但是我没有找到正确的答案来做我想做的事情。

实际上,我尝试通过Mongoose在MongoDB中保存两个不同的JSON对象列表。要同时执行两个操作,请使用“异步”。
但是,当我使用命令insertMany()保存它时,出现错误,因为他在完成insertMany()之前调用了异步回调。因此未定义答案[0]。

正确的做法是什么?

这是我的异步代码:

const mongoose = require("mongoose");
const async = require("async");
const utils = require("../utils");

const experimentCreate = function(req, res) {
  let resData = {};
  let experimentList = req.body.experiment;
  let datasetList = req.body.datasetList;

  async.parallel(
        {
          dataset: function(callback) {
            setTimeout(function() {
              answer = utils.createDataset(datasetList);
              callback(answer[0], answer[1]);
            }, 100);
          },
          experiment: function(callback) {
            setTimeout(function() {
              answer = utils.createExp(experimentList);
              callback(answer[0], answer[1]);
            }, 100);
          }
        },
        function(err, result) {
          if (err) {
            console.log("Error dataset or metadata creation: " + err);
            sendJSONresponse(res, 404, err);
          } else {
            console.log("Experiment created.");
            resData.push(result.dataset);
            resData.push(result.experiment);
            console.log(resData);
            sendJSONresponse(res, 200, resData);
          }
        }
      );
};


然后,在另一个文件中,名为createExp和createDataset的两个函数相同。像这样:

const createDataset = function(list) {
  let datasetList = [];
  for (item of list) {
    let temp = {
      _id: mongoose.Types.ObjectId(),
      name: item.name,
      description: item.description,
      type: item.type,
    };
    datasetList.push(temp);
  }

  Dataset.insertMany(datasetList, (err, ds) => {
    if (err) {
      console.log("Error dataset creation: " + err);
      return [err, null];
    } else {
      console.log("All dataset created.");
      return [null, ds];
    }
  });
};

最佳答案

您的代码有一些问题。首先,您没有在createDataset函数中返回任何内容。您正在insertMany的回调中返回一个值,但它不会将该值返回给createDataset的调用者,因为它在另一个作用域之内。要解决此问题,您可以将Dataset.insertMany包装在promise中,并根据Data.insertMany的结果来解决或拒绝,如下所示:

const createDataset = function(list) {
  let datasetList = [];
  for (item of list) {
    let temp = {
      _id: mongoose.Types.ObjectId(),
      name: item.name,
      description: item.description,
      type: item.type,
    };
    datasetList.push(temp);
  }

  return new Promise((resolve, reject) => {
    Dataset.insertMany(datasetList, (err, ds) => {
      if (err) {
        console.log("Error dataset creation: " + err);
        reject(err);
      } else {
        console.log("All dataset created.");
        resolve(ds);
      }
    });
  });
};


现在,您的返回对象不再是数组,因此您将无法通过answer[0]answer[1]访问错误和结果。在调用then并在createDataset调用中使用callback(null, answer)(这意味着then成功执行)之后,您将需要链接createDataset调用,或者如果callback(err)抛出,则使用createDataset如下错误:

dataset: function(callback) {
  setTimeout(function() {
    utils.createDataset(datasetList).then(answer => {
      callback(null, answer);
    }).catch(err => callback(err)); // handle error here);
  }, 100);
}


注意:如果还使用异步功能,则很可能需要更改createExp代码,使其在结构上类似于我上面生成的代码。

10-08 16:36