0

I have this script that I use to import some data from an API, and into my database. Since this process is very time consuming, it often times out because on some of the items processed there is a lot of data to process..

I came with this solution a while ago, using promises, to first do the request to the API, then after it finishes I would prepare the data and put it into a temporary csv file, then I would fire another request to split that file into multiple smaller files, then... you get the idea... it was working, but I need to add to it some extra requests, I just can't make it work... I probably just need to simplify my logic.

Anyone can help me improve this code to make it easier to add those extra requests and keep it sending one request after the other?

This is the (over simplified) script in question:

window.importTrialsScripts = {};

window.addEventListener('DOMContentLoaded', function() {
  importTrialsScripts.app.initialize();
});

(function(importTrialsScripts, document, $) {
  importTrialsScripts = importTrialsScripts || {};

  const app = {
    ajaxurl: 'myajaxurl',

    initialize: function() {
      this.submitHandler();
    },

    submitHandler: function() {
      const self = this;

      document.querySelector('#start-import').addEventListener('click', function() {
        self.pullTrialsFromApi();
      });
    },

    pullTrialsFromApi: function() {
      let data = new FormData();
      data.append('action', 'pull_trials_from_api');

      [123, 456, 789].forEach(function(str) {
        data.append('ids[]', str);
      });

      this.startPullingTrials(data);
    },

    startPullingTrials: function(data) {
      const self = this;

      let promise = new Promise(function(resolve, reject) {
        self.sendAjaxRequest(data, function() {
          if (this.status === 200) {
            const response = JSON.parse(this.response);

            if (! response.success) {
              alert('The API could not be reached. Please try again.');
              console.error('Error!!', response);
              return;
            }

            resolve(response.data);
          }
          else {
            console.error('there was an error in the request', this);
            reject(this);
          }
        });
      });

      promise.then(function(chunks) {
        const processingChunks = Object.values(chunks).map(function(chunk) {
          return self.processChunk(chunk);
        });

        Promise.all(processingChunks).then(function (processedTrials) {
          console.log('finished', processedTrials);
        });
      }, function(err) {
        console.error('promise rejected', err);
      });
    },

    processChunk: function(chunkTrials) {
      const self = this;

      let data = new FormData();
      data.append('action', 'process_trials_chunk');

      Object.values(chunkTrials).forEach(function(chunk) {
        data.append('chunk[]', JSON.stringify(chunk));
      });

      return new Promise(function(resolve, reject) {
        self.sendAjaxRequest(data, function() {
          if (this.status === 200) {
            const response = JSON.parse(this.response);

            if (! response.success) {
              console.error('Error!!', response.data);
              return;
            }

            resolve(response.data);
          }
          else {
            console.log('there was an error in the request', this);
            reject(this);
          }
        });
      });
    },

    splitToMultipleFiles: function() {
      const self = this;

      const data = new FormData();
      data.append('action', 'split_location_files');

      return new Promise(function(resolve, reject) {
        self.sendAjaxRequest(data, function() {
          if (this.status === 200) {
            const response = JSON.parse(this.response);

            if ( ! response.success ) {
              console.error('Error!!', response.data);
              return;
            }

            resolve(response.data.files);
          }
          else {
            console.log('there was an error in the request', this);
            reject(this);
          }
        });
      });
    },

    processLocation: function(file) {
      const self = this;

      let data = new FormData();
      data.append('action', 'process_location_data');
      data.append('file', file);

      return new Promise(function(resolve, reject) {
        self.sendAjaxRequest(data, function() {
          if ( this.status === 200 ) {
            const response = JSON.parse(this.response);

            if (! response.success) {
              console.error('Error!!', response.data);
              return;
            }

            resolve(response.data);
          }
          else {
            console.log('there was an error in the request', this);
            reject(this);
          }
        });
      });
    },

    sendAjaxRequest: function(data, callback) {
      const self = this;

      let xhr = new XMLHttpRequest();
      xhr.open('POST', ajaxurl);

      xhr.onload = callback;

      xhr.addEventListener('timeout', function(e) {
        console.error('the request has timed out', e);
      });

      xhr.addEventListener('error', function(e) {
        console.error('the request returned an error', e);
      });

      xhr.addEventListener('abort', function(e) {
        console.error('the request was aborted', e);
      });

      xhr.send(data);
    },
  };

  $.extend(importTrialsScripts, {
    app: app
  });

}).apply(this, [window.importTrialsScripts, document, jQuery]);
andrux
  • 2,782
  • 3
  • 22
  • 31
  • You can use `async` and `await` to conveniently arrange the order of promises. – xhg Jul 08 '21 at 21:09
  • I was hoping not to use async/await, for the case where I don't have support for those in my project. – andrux Jul 09 '21 at 00:20
  • Does this answer your question? [Resolve promises one after another (i.e. in sequence)?](https://stackoverflow.com/questions/24586110/resolve-promises-one-after-another-i-e-in-sequence) – xhg Jul 09 '21 at 23:05
  • Solution not using `async/await`: https://stackoverflow.com/a/41115086/2361752 – xhg Jul 09 '21 at 23:06
  • That last one looks interesting... I'll test it out shortly, thanks! – andrux Jul 23 '21 at 20:08

0 Answers0