Массив промисов Bluebird .all или .settle зацикливается на методах модели Loopback

Я пытаюсь перебрать кучу записей, выполнить поиск для каждой, а затем выполнить некоторые перестановки во внутреннем поиске (0-> 1, 0-> 2, 0-> 3, 1-> 2, 1-> 3 , 2->3) и запишите перестановки в таблицу. У меня есть работающий синхронный скрипт, но я не могу понять, как лучше всего использовать bluebird и методы модели с петлевой обратной связью.

Если я запускаю его асинхронно со своим сценарием, обработка занимает слишком много времени, а иногда мне не хватает памяти - и все это с самого начала требует памяти: ничего не записывается в БД, пока все перестановки не будут выполнены. был зациклен. Это может быть из-за PersistedModel, поэтому может быть полезно перейти прямо к node-mysql с помощью promisifyAll().

В конце концов, хотелось бы распараллелить это, чтобы записать все перестановки за поездку одновременно.

Сначала я завернул вызовы 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() и сохранил массив промисов, чтобы затем я мог использовать Promise.settle() только для выхода, когда все новые маршруты были записаны в ДБ. И правильно свяжите все это с .then()s.

В сочетании с созданием одной плавающей оболочки и нескольких других оберток промисов основной цикл выполнения выглядит примерно так:

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(). Нужно использовать меньше памяти и сократить время выполнения.


person notbrain    schedule 20.04.2015    source источник
comment
Я действительно не понимаю, что здесь не работает, может быть, дело в том, что getHopsFor увольняют за все поездки параллельно. Можете ли вы показать нам свои работающие синхронные и вложенные асинхронные обратные вызовы сценарии, чтобы мы могли показать вам, как воспроизвести их поведение с обещаниями?   -  person Bergi    schedule 20.04.2015


Ответы (1)


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)
    }
  }
}
person generalhenry    schedule 20.04.2015
comment
Вы заметили, что ваша версия ES7 делает что-то отличное от первых двух? - person Bergi; 20.04.2015
comment
Вы должны использовать for await при зацикливании на асинхронной области. - person Anatsu; 28.10.2020