蓝鸟数组的承诺.all或.settle循环在Loopback模型方法

时间:2015-04-20 18:28:19

标签: javascript node.js loopbackjs bluebird

我试图循环遍历一堆记录,对每个记录执行查找,然后对内部查找执行一些排列(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()。需要使用更少的内存并缩短执行时间。

1 个答案:

答案 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)
    }
  }
}