Node JS обещание - запустить функцию несколько раз с параметром из предыдущего запуска - PullRequest
0 голосов
/ 19 сентября 2018

В моем предыдущем посте мне удалось решить мою проблему с Обещанием, просмотрев некоторые примеры, предоставленные этим сообществом.Я надеюсь, что этот вопрос тоже будет легко решить, хотя я просто не могу разобраться с этим.Впервые в жизни я чувствую, что бегло говорить на языке PHP - это бремя.

Мой код выглядит так:

let getProducts = function(){
  countProducts
    .then(function(number){
      var name = '';
      let list = [];
      getProductNames(name)
        .then(function(names){
          names.forEach(function(el){
            list.push(el);
          });
          name = list.pop();
          getProductNames(name)
            .then(function(names){
              names.forEach(function(el){
                list.push(el);
              });
              ... and some more code to put the names in a table

функция getProductNames выглядит следующим образом:

var getProductNames = 
function(name) {
  return new Promise(
        function(resolve, reject){
            xyz.api.checkProducts(name, 1000, function(err, names){
              if (err){
                reject(err);
              } else {
                resolve(names);
              } 
            });
        }
  );
}

Это работает, потому что я знаю, что у меня менее 2000 продуктов, каждая проверка возвращает 1000 продуктов, поэтому мне нужно дважды запустить функцию getProductNames.

То, что я ищу, - это способ сделатьэто в цикле, так что он автоматически запускает необходимое количество запусков.

Проблема с вызовом API заключается в том, что для начала требуется имя продукта.Первый прогон без имени, это возвращает первую 1000. Для второго прогона мне нужно последнее найденное имя продукта прогона 1, для прогона 3 мне нужно последнее найденное имя продукта 2 и так далее.

Существуют различные способы определить, нужен ли еще один прогон:

  • сравнить длину массива с числом созданных продуктов
  • определить количество прогонов заранее.деление числа countПродукты, сгенерированные на 1000 (ceil ())
  • сравнить последнее найденное имя с новым последним найденным именем

Я просто не знаю, как выполнить цикл и где.Я предполагаю, что решение найдено путем добавления вспомогательной функции, но когда я пытаюсь это сделать, я попадаю в значения, недоступные и т. Д.

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

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

Я положил комментарии, где это необходимо, чтобы лучше понять код.Не стесняйтесь спрашивать.

примечание: этот код не проверен и может не работать как есть.Это просто, чтобы показать вам, как на самом деле это сделать.

note1: Вы также можете посмотреть на async-await, это то же самое, что и обещание, но синтаксически более читабельное и понятное

let getProducts = function() {
  // return your promise, you may want to getProducts.then()
  return countProducts() 
    .then(function(number) {
      return getProductNames(number);
    })
    .catch(function(err) { // always put a catch
       console.log('there was an error', err)
    })
}


// make your getProductsName take in number value
// the name it takes is empty by default, we will provide name when we recursively call it
let getProductNames = function(number, name = ''){
  // check if your number is less than -1000 here , why ? keep reading the code
  if (number < -1000) return [];
  const nameCount = 1000;
  let names = []
  return callAPI({name, nameCount})
    .then(function(namesFromCallAPI) {
       names = names.concat(namesFromCallAPI); // you can concat two arrays at once
       // I do not know why you are poping the names, since it will mutate the array
       // use any one as per requirement
       let newName = names.pop();
       // OR let newName = names[names.length-1]; which will not mutate the array
       // recursively call the function by decreasing it by your nameCount
       // when your number is 500, it can still call but the result will be -500, which will run
       // in the next iteration -500-1000 will be -1500 which is < -1000 (explanation of base condition)
       return getProductNames(number - nameCount, newName)
    })
    .then(function(res) {
      // the result from getProductNames is again concatinated to our names and returned
      return names.concat(res);
    })
    .catch(function(err) {
       // always put a catch in your chain
       console.log('There was an error in our recursive function', err);
    })
}


// make a separate function that would api call
// put any parameters that you may need to make customizable here
let callAPI = function(params) {
  return new Promise(function(resolve,reject) {
    xyz.api.checkProducts(params.name, params.nameCount, function(err, names){
      if (err){
        reject(err);
      } else {
        resolve(names);
      } 
    });
  })
}
0 голосов
/ 19 сентября 2018
let getProducts = function () {
    let list = [];
    const fn = function (name, number) {
        return getProductNames(name).then(function (names) {
            names.forEach(function (el) {
                list.push(el);
            });

            if(list.length >= number || names.length == 0) {
                return list;
            }

            return fn(list.pop(), number); // Add promise to your chain
        });
    }
    return countProducts.then(function (number) {
        return fn('', number);
    });
}

// Use
getProducts().then(function(items) {
    console.log(items.length);
}, function(err) {
    console.error(err);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...