在另一个find(...)的回调中查找,如何逃离回调地狱?

Posted

技术标签:

【中文标题】在另一个find(...)的回调中查找,如何逃离回调地狱?【英文标题】:Find inside callback of another find (...), how to escape from callback hell? 【发布时间】:2015-06-05 16:00:13 【问题描述】:

(首先:对不起,我的英语不太好!)

我想在一个数组中返回 3 个查找的结果。 我的代码(下一个)运行良好,但我陷入了回调地狱!

_Schema
  .static('retrieveAll', function(cb) 
    query = ;
    this.find(query, function(err, data) 
      if(err) 
        cb(err, null);
        return;
      

      if(data)
        all = data;
      else
        all = [];

      _StoresModel.find(query).select('contact address').exec(function(err, data) 
        if(err) 
          cb(err, null);
          return;
        

        if(data) 
          all = data.reduce(function(coll, item) 
            coll.push(item);
            return coll;
          , all);
        

        _CustomersModel.find(query).select('contact address').exec(function(err, data) 
          if(err) 
            cb(err, null);
            return;
          

          if(data) 
            all = data.reduce(function(coll, item) 
              coll.push(item);
              return coll;
            , all);
          

          cb(null, all);          
        );
      );
    );
  );

我在一个 FIND 里面有一个 FIND。 有什么可以改进的吗?

解决方案:

_架构 .static('retrieveAll', function(cb) var model = this;

_async.parallel(
   contacts: function(cb) 
      model.find().exec(cb);
    
  , stores: function(cb) 
      _StoresModel.find().select('contact address').exec(cb);
    
  , costumers: function(cb) 
      _CostumersModel.find().select('contact address').exec(cb);
    
  
, function(err, data) 
  if(err) 
    cb(err, null);
    return
  

  var ret = [];
  if(data.contacts.length > 0) 
    ret = ret.concat(data.contacts);
  
  if(data.stores.length > 0) 
    ret = ret.concat(data.stores);
  
  if(data.costumers.length > 0) 
    ret = ret.concat(data.costumers);
  

  cb(null, ret);
);

【问题讨论】:

【参考方案1】:

您可以尝试使用Promises。

(未经测试)示例:

var RSVP = require('rsvp');
var all = [];

_Schema.static('retrieveAll', function(cb) 
    query = ;

    findPromise(this, query)
    .then(function (data) 
        all = data;
        return findPromise(_StoresModel, query, 'contact address');
    )
    .then(function (stores) 
        all = all.concat(stores);
        return findPromise(_CustomersModel, query, 'contact address');
    )
    .then(function (customers) 
        all = all.concat(customers);
        cb(null, all);
    )
    .catch(function (err) 
        cb(err, null);
    );
);

function findPromise(Model, query, select) 
    return new RSVP.Promise(function (resolve, reject) 
        Model.find(query).select(select || '*').exec(function (err, data) 
            return err ? reject(err) : resolve(data);
        );
    );

该示例使用RSVP,但也有其他的promise 实现,例如Q 和bluebird。

附带说明,您可以使用concat 来连接数组,而不是使用reduce

【讨论】:

【参考方案2】:

看看 npm Async。它是一个很棒的库,可以在 node.js 上使用不同的模式。

如果有按时间顺序排列的优先级,您可能希望使用waterfall;如果它们都可以并行执行,您可能希望使用parallel 模式。

【讨论】:

【参考方案3】:

q 和 bluebird 等一些服务器端 promise 库会大幅清理您的代码并消除回调地狱的混乱。

【讨论】:

以上是关于在另一个find(...)的回调中查找,如何逃离回调地狱?的主要内容,如果未能解决你的问题,请参考以下文章

留在一线,逃离一线?我从上海举家回成都的生活经历告诉你

留在一线,逃离一线?我从上海举家回成都的生活经历告诉你

如何通过CMake查找特定/本地文件

火炬:如何在另一个线程中注册一个火炬回调?

Mongoose find() 回调问题

在另一列SQL的连接信息中查找一列信息