Node JS promise - run function multiple times with parameter from former run

时间:2018-09-19 08:24:08

标签: node.js promise

In my former post I was able to solve my Promise problem by looking at some examples provided by this community. I hope this one will be easy to solve too, although I just can't get my head around it. For the first time in my life, I experience being fluent in PHP language is a burden.

My code looks like this:

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

the getProductNames function looks like this:

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);
              } 
            });
        }
  );
}

This works because I know I have less than 2000 products, each check returns 1000 products, so I have to run the getProductNames function twice.

What I am looking for is a way to make this into a loop so it automatically runs the needed number of runs.

The problem with the api call is that it needs a productname to start with. The first run is without a name, this returns the first 1000. For the second run I need the last found productname of run 1, for run 3 I need the last found productname of 2, and so on.

There are different ways to determine whether another run is needed:

  • compare length of array with the number countProducts generated
  • determine the number of runs on forehand by dividing the number countProducts generated by 1000 (ceil())
  • compare last found name with new last found name

I just don't know how to loop and where. I assume the solution is found by adding a helper function, but when I try that I get caught in values not being available and so on.

You don't have to solve my problem, but I would be very grateful if some one could supply an example of the needed structure or some internet source that describe this structure. The examples I found don't use values from the former runs.

2 个答案:

答案 0 :(得分:1)

BUILDARGS did not return a HASH reference

答案 1 :(得分:1)

为了更好地理解代码,我在需要的地方添加了注释。随便问什么。

注意:此代码未经测试,可能无法按原样工作。这只是向您展示如何实际操作。

note1:您可能还想看看async-await,它们与promise一样,但是在语法上更加可读和清晰

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);
      } 
    });
  })
}