Dropbox JS SDK: execute i++ inside .then-function

234 Views Asked by At

I struggled somewhat naming this question, but I'll try to explain it rather quickly.

I'm using the Dropbox JavaScript SDK to retrieve shared links from specific folders. First of all, I'm using the following code to retrieve files from a folder:

var DROPBOX_PATH = path;
var ACCESS_TOKEN = '***';
var dbx = new Dropbox({ accessToken: ACCESS_TOKEN });

function listFiles() {
  dbx.filesListFolder({ path: DROPBOX_PATH })
    .then(function(response) {
      displayFiles(response.entries);
    })
    .catch(function(error) {
      console.error(error);
    });

  return false;
}

I will then loop through these files to use dbx.sharingGetSharedLinks(), dbx.filesGetTemporaryLink() as well as dbx.sharingGetSharedLinkFile() and get their links. The thing is, this process can take some time if the folder contains a couple of files and I want to use a <progress> element to show how far the progress has gone.

First, I tried to use a for(var i = 0; i < files.length; i++) loop to wrap the three functions mentioned above, and add i to progress bar value under dbx.sharingGetSharedLinkFile()'s .then() process, but they're not in sync -- the i value is increased before all of those functions reach their respective ends and can output anything.

I tried instead to replace it with a while() loop and put i++ inside the last dbx function, but that just makes my web browser go overload and possibly end up in an endless loop.

Is there any way to have the i value increase in correspondence with dbx.sharingGetSharedLinkFile().then()?


2

There are 2 best solutions below

0
On

To achieve expected behaviour you need to iterate using a function instead of a cycle.

Your current code wont work like expected because callback of dropbox api method sharingGetSharedLinks will run only after async request to a dropbox server (inside this method) will be done, while main loop continue iterating through the files list.

Finally, it's all about promises so i try to point you in a right direction with this link MDN about Promises and little code example:

function displayFiles(files) {

        //... your code
        // i'll show you only changes

        var i = 0;

        (function listNextFile(){


          let file = files[i]

          if (file) {

            var name = file.name.slice(4).slice(0, -7).replace('_', '/'),
                file_path = file.path_display;

            dbx.sharingGetSharedLinks({ path : file_path }).then(function(response){

              // ...
              // there is your code
              // after all you need to icrease counter and call function again

              i++
              listNextFile();

            });

          }

        })()

}
0
On

Your code is really messy. If you're able to use es6, or q library. Just use promises like this.

var promises = [];
  

files.forEach((file) => {
  promises.push(sharingGetSharedLinks(file_path).then(filesGetTemporaryLink(download_path)).then(sharingGetSharedLinkFile(download_url)));
});

Promise.all(promises).then((values) => {
//   values are, an array of responses where each response is the three requests per each file
});

Separate the logic for each request sharingGetSharedLinks returns the result for this request and process it, filesGetTemporaryLink do the same thing with the result of sharingGetSharedLinks and make a new http request, then the last one repeat the process but with the result of filesGetTemporaryLink.

Then you have to be able to handle all the requests together. [r1, r2, ...] where r1 includes the process of request to sharingGetSharedLinks, filesGetTemporaryLink, and sharingGetSharedLinkFile.

But you have to refactor all your code, here it's a how simply is to use Promises https://www.promisejs.org/patterns/