Обещания в то время как L oop, где условие while основано на результате обещания - PullRequest
0 голосов
/ 18 марта 2020

Мне нужно сделать неопределенное l oop, где условие l oop будет основано на ответе от обещания в l oop, которое получает некоторые данные из базы данных. L oop должен быть выполнен из обещания, которое затем возвращает полный список записей, извлеченных из базы данных. Это несколько упрощено по сравнению с реальным примером, но я попытался предоставить базовый код c, чтобы продемонстрировать, что я хочу сделать по существу.

Вызов getLinkedEntities проходит в сущности и на основе идентификатора связанной сущности начинается с l oop, где связанные сущности возвращаются, а затем возвращаются из исходного обещания.

Проблема, с которой я столкнулся заключается в том, что из-за асинхронной природы обещаний в тот момент, когда getElement вызывается в то время как l oop, он никогда не разрешается, потому что функция продолжается и застревает в непрерывном l oop.

Надеюсь, этот код достаточно хорошо описывает что я пытаюсь сделать, то есть получить массив связанных сущностей, но как это сделать синхронно, чтобы все обещания возвращались?

   function getLinkedEntities(startEntity) { 
        return new Promise(function (resolve, reject) {

            var linkedEntities = [];
            var entityId = startEntity.id;
            var someOtherId = startEntity.linkedentityid;

            var stopLoop = false;

            do {

                getElement(someOtherId).then(function (entity) {
                    linkedEntities.push(entity)
                    entityId = entity.id;
                    someOtherId = entity.linkedentityid;
                    stopLoop = entity.linkedentityid === null ? 1 : 0;
                });

            }
            while (!stopLoop);

            resolve(linkedEntities);

        });
    }

    function getElement(id) {
        return new Promise(function (resolve, reject) {
            // go to database and get an entity
            resolve(entity);
        });
    }

    getLinkedEntities(someEntity).then(function (response) {
        // do somethign with linkedEntities
    });

1 Ответ

1 голос
/ 18 марта 2020

Без использования async / await вы можете создать внутреннюю функцию, которая сама себя вызывает.

например.

  ...
  function getNext() {
     return getElement(someOtherId).then(function (entity) {
       linkedEntities.push(entity)
       entityId = entity.id;
       someOtherId = entity.linkedentityid;
       stopLoop = entity.linkedentityid === null ? 1 : 0;
       if (stopLoop) return resolve(linkedEntities);
       else return getNext();
     });
  }
  //boot strap the loop
  return getNext();
}

По сути, это просто вызывает getNext до stopLoop устанавливается, а затем разрешается linkedEntities, если нет, то снова вызывает getNext. IOW: именно то, что делает ваш l oop.

Ниже приведен рабочий фрагмент, который использует эту идею, вместо getElement, я заменил обещание сна. В основном заполнить это массив ожидания 500 мс между каждым массивом pu sh.

function sleep(ms) {
  return new Promise(function (resolve) {
    setTimeout(resolve, ms);
  });
}

function test() {
  var ret = [];
  function getNext() {
    return sleep(500).then(function () {
      if (ret.length >= 10) {
        return ret;
      } else {
        console.log('tick: ' + ret.length);
        ret.push(ret.length + 1);
        return getNext();
      }
    });
  }
  return getNext();
}

test().then(function (r) {
  console.log('Resolved with ->');
  console.log(r.join(','));
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...