2016-06-27 14 views
1

次のコード例があります。JavaScriptプロミス依存関係処理

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の後に電話することができません。 https://github.com/caolan/async#control-flow

シリーズ並列キュー方法を確認してください:

+0

あなたの正確な問題は何ですか?あなたは上記の状況に対処する約束を使用したいですか?そして、「私はすべてのダウンロードが解決されるのを待つことができず、後にプロセスを呼び出すことができません。 – Dnyanesh

+0

あなたのコードは「モデルの必要なモデル」について何も表示していません。 –

+0

ちょっと@Dnyanesh、あなたの返信ありがとう、私は理解しやすくするために私の例を更新しました。 – Adam

答えて

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();

+0

FYI、あなたの 'function delay()'はすでにbluebirdで 'Promise.delay()'として実装されています。 – Tomalak

+0

ありがとう、私はコードでそれを言及する –

+0

素晴らしい!ありがとう@TamasHegedus! – Adam

0

非同期モジュールは、仕事を行います。

+0

ありがとうございますが、どのように依存関係を処理しますか? – Adam

関連する問題