【问题标题】:how to force a call to be synchronous in node.js如何在 node.js 中强制调用同步
【发布时间】:2019-05-14 20:36:30
【问题描述】:

请看下面的代码sn-p。我希望只有在获得第一个查询的结果后才执行第二个 MongoDB 查询。但正如你可以想象的那样,它不会按照这个顺序发生。

db.collection('student_profile', function (err, stuColl) {
  //This if-else can be refactored in to a seperate function
  if (req.params.stuId == req.header('x-stuId')) {
    var stuInQuestion = student;
  } else {
    var stuInQuestionId = new ObjectID.createFromHexString(req.params.stuId);
    stuColl.findOne({
      '_id': stuInQuestionId
    }, function (err, stuInQuestionObj) {
      if (!stuInQuestionObj) {
        process.nextTick(function () {
          callback(null);
        });
      } else {
        var stuInQuestion = stuInQuestionObj;
      }
    });
  }

  stuColl.find({
    '_id': {
      $in: stuInQuestion['courses']
    }
  }).limit(25).sort({
    '_id': -1
  }).toArray(function (error, courses) {
    if (error) {
      process.nextTick(function () {
        callback(null);
      });
    } else {
      process.nextTick(function () {
        callback(courses);
      });
    }
  });
});

那么我在这里的选择是什么?

  1. 有没有办法以不需要任何控制流库的方式对此进行编码?如果是,有人可以告诉我怎么做吗?

  2. 如果这确实需要使用控制流库,我应该使用哪一个?异步,FuturesJs,还有什么?

【问题讨论】:

    标签: javascript node.js mongodb express


    【解决方案1】:

    您不需要任何控制流库,因为这些库只是在后台使用回调。

    试试这样的:

    db.collection('student_profile', function (err, collection) {
    
      // Suppose that `firstQuery` and `secondQuery` are functions that make your
      // queries and that they're already defined.
      firstQuery(function firstCallback(err, firstRes) {
    
        // Do some logic here.
    
        // Make your second query inside the callback
        secondQuery(function secondCallback(err, secondRes) {
          // More logic here
        });
      });
    });
    

    基本上,您要做的是从第一个查询的回调中调用您的第二个查询。

    这可能会让您觉得嵌套很深。如果这成为一个问题,您可以通过定义函数而不是内联所有函数以及将逻辑包装在模块中来缓解它。

    【讨论】:

    • @Joshua...感谢您的回复。我熟悉嵌套构造,并在我的代码中的多个位置使用它。但上述情况不同。我有一个 if-else 构造。第一个查询在 else 部分。第二个查询在 if-else 之外,无论在 if-else 子句中满足哪个条件,都需要执行。因此,在不重复代码的情况下嵌套它变得很困难(if 和 else 部分中的代码相同。)非常感谢您的帮助。
    【解决方案2】:

    我会创建一个findStudent 函数并让两种情况都调用它:

    db.collection('student_profile', function (err, stuColl) {
      //This if-else can be refactored in to a seperate function
      if (req.params.stuId == req.header('x-stuId')) {
        return findStudent(student);
      } else {
        var stuInQuestionId = new ObjectID.createFromHexString(req.params.stuId);
        stuColl.findOne({
          '_id': stuInQuestionId
        }, function (err, stuInQuestionObj) {
          if (!stuInQuestionObj) {
            process.nextTick(function () {
              callback(null);
            });
          } else {
            return findStudent(stuInQuestionObj);
          }
        });
      }
    
      function findStudent(stuInQuestion) {
        stuColl.find({
          '_id': {
            $in: stuInQuestion['courses']
          }
        }).limit(25).sort({
          '_id': -1
        }).toArray(function (error, courses) {
          if (error) {
            process.nextTick(function () {
              callback(null);
            });
          } else {
            process.nextTick(function () {
              callback(courses);
            });
          }
        });
      }
    });
    

    【讨论】:

    • @Dan....我接受了你的建议,因为它看起来很简单。有用。谢谢大家的意见。
    • 不就是重写了异步调用的回调函数吗?这个答案如何强制代码同步执行?
    猜你喜欢
    • 1970-01-01
    • 2013-10-16
    • 1970-01-01
    • 2016-11-21
    • 2012-05-14
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多