在另一个Find(..)的回调内部查找,如何逃离回调地狱

Find inside callback of another find (...), how to escape from callback hell?

本文关键字:回调 何逃离 地狱 逃离 内部 另一个 Find 查找      更新时间:2023-09-26

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

我想在一个数组中返回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);          
        });
      });
    });
  });

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

解决方案:

_架构.static('RetriveAll',函数(cb){var模型=此;

_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);
});

您可以尝试使用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

来看看npm-Async。这是一个可以在node.js.上使用的不同模式的伟大库

如果有Chronological优先级,您可能会想要使用瀑布,如果它们都可以并行执行,则可能会使用并行模式。

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