JavaScript承诺依赖性处理

时间:2016-06-27 13:27:50

标签: javascript node.js promise bluebird

我有以下代码示例。

var Promise = require('bluebird');

var model = function (object) {
    this.name = object.name;
};

model.prototype.download = function () {
    var self = this;
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve();
        }, Math.random() * 100)
    });
};

model.prototype.process = function () {
    var self = this;
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('processed: ', self.name);
            resolve();
        }, Math.random() * 100)
    });
};



var models = [new model({
    name: 'user',
    requires: ['company']
}), new model({
    name: 'address',
    requires: ['user', 'company']
}), new model({
    name: 'company'
})];

Promise.map(models, function (model) {
    return model.download()
        .then(function () {
            return model.process();
        });
});

此代码的必需输出为:

processed: company // 1rst, because company model has no dependencies
processed: user // 2nd, because user requires company
processed: address // 3rd, because address requires company and user

我需要以某种方式管理依赖项。仅当模型所需模型的所有model.process函数都已解决时,才应触发process函数。

这只是一个小例子,我有很多具有多个依赖关系的模型。

我需要同步触发download个功能,并尽快触发process功能。我等不及要解决所有下载问题,并在之后致电process

2 个答案:

答案 0 :(得分:2)

这是一个示例,您可以异步遍历有向非循环图,而无需多次评估各个节点。请注意,依赖关系图中的循环会导致此实现中的死锁。

function Model(name, requires) {
  this.name = name;
  this.requires = requires;
};


// this function is available as `Promise.delay` when using bluebird
function delay(x, v) {
  return new Promise(resolve => {
    setTimeout(() => { resolve(v); }, x);
  });
}

Model.prototype.process = function () {
  console.log('started processing: ', this.name);
  return delay(Math.random() * 100 + 100).then(() => {
    console.log('finished processing: ', this.name);
  });
};

function Processor(models) {
  this.processMap = {};
  this.models = models;
  
  models.forEach(m => {
    this.processMap[m.name] = {
      promise: null,
      model: m
    };
  });
}

Processor.prototype.processDependencies = function(model) {
  return Promise.all(model.requires.map(r => this.processByName(r)));
};

Processor.prototype.process = function(model) {
  const process = this.processMap[model.name];
  if (!process.promise) {
    process.promise = this.processDependencies(model)
      .then(() => model.process());
  }
  return process.promise;
};

Processor.prototype.processByName = function(modelName) {
  return this.process(this.processMap[modelName].model);
};


function test() {
  const models = [
    new Model('bottom', []),
    new Model('mid a', ['bottom']),
    new Model('mid b', ['bottom']),
    new Model('top', ['mid a', 'mid b'])
  ];
  
  const processor = new Processor(models);

  Promise.all(
    models.map(m => processor.process(m))
  ).then(allResults => {
    console.log("All process finished");
  }, e => {
    console.error(e);
  });
}

test();

答案 1 :(得分:0)

异步模块将完成工作:https://github.com/caolan/async#control-flow

检查系列并行队列方法。

相关问题