0

I have a set of nested promises shown below. The expected behaviour here is for 1 to be printed, then 2 to be printed and then for the callback to be called under dropbox_functions.moveFolder('test', data.ui). However what is happening is that 1 is printed then 2 is printed and the 2.1 is printed, so the 2 promise is going into the then and the catch. I cant work out why.

dropbox_functions.createBatchFolder(data.ui)
        .then(function(response) {
          console.log('1')
          console.log(response)
          dropbox_functions.checkScannerFolderExists('test')  
            .then(function(response) {
              console.log('2')
              console.log(response)
              dropbox_functions.moveFolder('test', data.ui)
                .then(function(response) {
                  console.log(response)
                  callback(null, data)
                })
                .catch(function(error) {
                  console.log(error);
                  callback('Data not copied from scanner', data)
                });
            })
            .catch(function(error) {
                console.log('2.1')
                console.log(response)
                dropbox_functions.createDataFolder(data.ui)
                  .then(function(response) {                      
                    console.log(response)
                    callback('No scanned folder', data)
                  })
                  .catch(function(error) {
                    console.log(error);
                    callback('Data Folder not created', data)
                  });  
            });
            // callback(null, data)
        })
        .catch(function(error) {
          console.log('1.2')
          console.log(error)
          callback('Folder not created', data)
        });
Arthur Le Calvez
  • 413
  • 2
  • 7
  • 17
  • 1
    Why are you nesting your promises? That’s the whole point of promises avoiding a callback hell – Pari Baker Dec 05 '18 at 18:40
  • This means that `dropbox_functions.moveFolder('test', data.ui)` generated an exception. Instead of doing `console.log('2.1')` it would be more useful to do `console.log('2.1', error)` so you know what the exception is. – trincot Dec 05 '18 at 18:41
  • 1
    You can create different promises and call then to resolve each promise and use 1 catch to resolve the errors. That does cause the issue of not knowing where the error occurred but in that case you can switch to async/await – Pari Baker Dec 05 '18 at 18:41
  • `dropbox_functions.moveFolder` is the reason of your error. Either the function is not available or `data.ui` is unavailable – PaulShovan Dec 05 '18 at 18:41
  • 1
    The way you have it set up one of the catches acts as a pass through. So it catches an error but then carries on resolving – Pari Baker Dec 05 '18 at 18:42
  • could you explain how you do 1 catch for all the promises – Arthur Le Calvez Dec 05 '18 at 18:44
  • and what do you mean by one catch acts as a pass through – Arthur Le Calvez Dec 05 '18 at 18:45
  • Have you printed the error yet? (see my previous comment) – trincot Dec 05 '18 at 18:45
  • yes i printed the error and it was coming from the moveFolder which wasnt returning a promise thanks – Arthur Le Calvez Dec 05 '18 at 19:07

2 Answers2

3

There must be an error thrown, after execution of line console.log('2'). If an error thrown within a promise execution, the next immediate catch block will catch the particular error.

              console.log('2')
              console.log(response) <-- Here 
              dropbox_functions.moveFolder('test', data.ui) <--- Here 
                .then(function(response) {
                  console.log(response)
                  callback(null, data)
                })
                .catch(function(error) { <-- or here
                  console.log(error);
                  callback('Data not copied from scanner', data)
                });
Janaka Chathuranga
  • 1,742
  • 16
  • 19
3

This isn't an answer but an recommendation. The whole point of promises is that you don't have to nest them, but can chain them instead. This is done by simply returning a new promise as return value of the function provided to then. You can then chain another then statement after it that handles the newly resolved promise.

dropbox_functions
  .createBatchFolder(data.ui)
  .then(function (response) { // response of createBatchFolder 
    console.log('1');
    console.log(response);
    return dropbox_functions.checkScannerFolderExists('test');
  })
  .then(function (response) { // response of checkScannerFolderExists
    console.log('2');
    console.log(response);
    return dropbox_functions.moveFolder('test', data.ui);
  })
  .then(function (response) { // response of moveFolder
    console.log(response);
    callback(null, data);
  })
  .catch(function (error) { // some error occurred
    console.error(error);
    callback(error, data);
  });

If you need to do something for specific errors you can check the name and/or description properties of the error or convert it to a string by calling toString() on it.


Furthermore by calling a callback function yourself you still introduce callback hell into your program. I'd recommend returning a promise instead and work with that. If the code above is the last statement of your function you can simply return a resolved promise from the last then statement.

function yourFunction() {
  // ...
  return dropbox_functions
    .createBatchFolder(data.ui)
    // ...
    .then(function (response) { // response of moveFolder
      console.log(response);
      return Promise.resolve([null, data]);
    })
    .catch(function (error) { // some error occurred
      console.error(error);
      return Promise.reject([error, data]);
    });
}

If it's not the last statement simply save the resulting promise into a variable and return that after you did you other stuff. You could even leave out the catch statement if all you do is forward it into Promise.reject(...) (this is currently not the case since you add data too). This can then be handled by the code calling yourFunction.

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52