如何在node.js中使用q.defer链接promises?

时间:2014-02-19 19:09:59

标签: javascript node.js promise q

exports.list = function(req, res) {
  var location_parent_id = req.params.location_parent_id;

  var query = {
    company_id: req.company_id
  };

  if(location_parent_id) {
    query.location_parent_id = location_parent_id;
    Location.findOne({someQuery}, function(err, location) {
      response.location = location;
    });
  } else {
    query.location_parent_id = {
      '$exists': false
    }
  }

  Location.find(query, function(err, locations) {
    if(err) {
      response = {
        status: 'error',
        error: err
      }
    } else if(!locations) {
      response = {
        status: 'error',
        error: 'Location not found'
      }
    } else {
      response = {
        status: 'ok',
        locations: locations
      }
      return res.json(response);
    }
  });
}

这是我的代码。如果有location_parent_id,那么我也想返回该位置。我认为承诺是执行我想要的好方法,而不是进入异步和回调地狱。只是不确定具体如何。

1 个答案:

答案 0 :(得分:7)

您根本不需要使用q.defer。您可以使用Node-callback interface methods立即获得承诺。要链接方法,请使用.then()

exports.list = function(req, res) {
  var result = Q.ninvoke(Location, "find", {
    company_id: req.company_id,
    location_parent_id: req.params.location_parent_id || {'$exists': false}
  }).then(function(locations) {
    if (!locations)
      throw new Error('Location not found');
    return {
      status: 'ok',
      locations: locations
    };
  });
  if (req.params.location_parent_id) {
    // insert the step to wait for the findOne (in parallel), and merge into res
    result = Q.all([result, Q.ninvoke(Location, "findOne", {someQuery})])
    .spread(function(res, location) {
      res.location = location;
      return res;
    });
  }
  result.catch(function(err) {
    return {
      status: 'error',
      error: err.message
    };
  }).done(function(response) {
    res.json(response);
  });
}