回调NodeJS并用mongoose插入数据

Callback NodeJS & insert data with mongoose

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

实际上,我尝试通过 Mongoose 在 MongoDB 中保存两个不同的 JSON 对象列表。为了同时执行两者,我使用 'async'。 但是,当我用命令 insertMany() 保存它时,我得到一个错误,因为他在完成 insertMany() 之前调用了异步的回调。因此 answer[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 函数中 returning 任何东西。您在 insertMany 的回调中 returning 一个值,但它不会 return 该值给 createDataset 的调用者,因为它在另一个范围内。要解决此问题,您可以将 Dataset.insertMany 包装在一个承诺中,并根据 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);
      }
    });
  });   
};

现在您的 return 对象不再是数组,因此您将无法通过 answer[0]answer[1] 访问错误和结果。在调用 createDataset 并在 then 调用中使用 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 代码也使用了异步函数,您很可能需要将其更改为在结构上与我上面生成的代码相似。