我试图循环遍历一堆记录,对每个记录执行查找,然后对内部查找执行一些排列(0-> 1,0-> 2,0-> 3,1-> ; 2,1-> 3,2-> 3)并将排列写入表格。我有一个工作的同步脚本,但我无法弄清楚如何最好地使用bluebird和loopback持久模型方法。
如果我用我的脚本异步运行它,处理时间太长,有时我的内存耗尽 - 整个事情就是内存耗尽:没有任何内容写入数据库直到所有排列都已经完成。这可能是因为PersistedModel所以使用promisifyAll()直接使用node-mysql可能很有用。
最终会喜欢将其并行化,以便同时写下每次旅行的所有排列。
首先,我在promises中包装了PersistedModel.create()和.find()调用:
function createRoute(newRoute) {
return new Promise(function(resolve, reject) {
Route.create(newRoute, function(err, route) {
if (!err) {
resolve(route);
} else {
reject(err);
}
});
});
}
function getHopsFor(trip) {
return new Promise(function(resolve, reject) {
Schedule.find({
where: {
name: trip.name,
tripCode: trip.tripCode,
companyCode: trip.companyCode
},
order: 'eta ASC',
}, function(err, hops) {
if(err) {
reject(err);
}
resolve(hops);
});
});
}
是的,这是一个反模式但我不能在库上使用.promisifyAll()(作为一个整体或显式地使用.create()),因为它有点不兼容。我认为原生的承诺还在路上但尚未准备好(如果我错了,请纠正我,所以我可以使用我已经拥有的承诺;))。
我的主要问题是如何循环上面的.find()和.create()promises并保存一个promises数组,这样我就可以使用Promise.settle()只在所有新路由都退出时才退出写到DB。并使用.then()正确链接整个事物。
结合创建一个单独的包装器和一些其他的包装器,主执行循环是这样的:
getTrips().then(function(trips){
for(t = 0; t < trips.length; t++) {
getHopsFor(trips[t]).then(function(hops) {
getRoutesFor(hops).then(function(routes) {
for(r = 0; r < routes.length; r++) {
routes.push((createRoute(route));
}
Promise.settle(routes).then(function(results){
console.log("finished trip " + t)
});
});
});
}
});
我的初始脚本使用嵌套回调并且有点可管理,但是想尝试使用Bluebird版本来绕过Promises.all()和.settle()。需要使用更少的内存并缩短执行时间。
答案 0 :(得分:0)
ES5 +承诺
function createRoutesForTrips () {
return getTrips().then(function(trips) {
return Promise.all(trips.map(function(trip) {
return getHopsFor(trip).then(function(hops) {
return getRoutesFor(hops);
}).then(function(routes) {
return Promise.all(routes.map(function(route) {
return createRoute(route);
}));
});
}));
});
}
ES6胖箭
var createRoutesForTrips = () =>
getTrips().then((trips) =>
Promise.all(trips.map((trip) =>
getHopsFor(trip).then((hops) =>
getRoutesFor(hops)
).then((routes) =>
Promise.all(routes.map((route) =>
createRoute(route)
))
)
))
)
ES7异步功能
async function createRoutesForTrips () {
let trips = await getTrips()
for (let trip of trips) {
let hops = await getHopsFor(trip)
let routes = await getRoutesFor(hops)
for (let route of routes) {
await createRoute(route)
}
}
}