JavaScript 承诺依赖处理
JavaScript Promise Dependency Handling
我有以下代码示例。
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
检查系列、并行和队列方法。
这是一个示例,您可以如何异步遍历有向无环图,而无需多次评估各个节点。请注意,依赖图中的循环会导致此实现中出现死锁。
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();
正如@ZdravkoTatarski 提到的,caolan async 有一个名为“auto”的控制流方法,它作为任务的依赖树(类似于 Gulp)。
请参阅下面适合您的用例的使用示例。
//Using Promises
async.auto({
company: function(callback) {
console.log('in company');
// async code to get some data
callback(null, 'company data');
},
user: ['company', function(callback) {
console.log('in user');
// async code to get some data
callback(null, 'user data');
}],
address: ['user', 'company', function(results, callback) {
console.log('in address');
// async code to process address for user&company
callback(null, {user: results.user, company: results.company, address: 'address data'});
}]
}).then(results => {
console.log('results = ', results);
// results = {
// user: 'user data',
// company: 'company data',
// address: {user: 'user data', company: 'company data', address: 'address data'}
// }
}).catch(err => {
console.log('err = ', err);
});
这里有完整的文档Caolan Async .auto。
我有以下代码示例。
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
检查系列、并行和队列方法。
这是一个示例,您可以如何异步遍历有向无环图,而无需多次评估各个节点。请注意,依赖图中的循环会导致此实现中出现死锁。
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();
正如@ZdravkoTatarski 提到的,caolan async 有一个名为“auto”的控制流方法,它作为任务的依赖树(类似于 Gulp)。
请参阅下面适合您的用例的使用示例。
//Using Promises
async.auto({
company: function(callback) {
console.log('in company');
// async code to get some data
callback(null, 'company data');
},
user: ['company', function(callback) {
console.log('in user');
// async code to get some data
callback(null, 'user data');
}],
address: ['user', 'company', function(results, callback) {
console.log('in address');
// async code to process address for user&company
callback(null, {user: results.user, company: results.company, address: 'address data'});
}]
}).then(results => {
console.log('results = ', results);
// results = {
// user: 'user data',
// company: 'company data',
// address: {user: 'user data', company: 'company data', address: 'address data'}
// }
}).catch(err => {
console.log('err = ', err);
});
这里有完整的文档Caolan Async .auto。