0

I am making a chrome extenction using JS. The function chrome.history.search is a async callback. Since it is async I plan to use promise to make it sync. I want the code to assign the value to url using chrome.history.search, and after that push it to the array lastEpisodeLink which is global. There is another function findLastEpisodeLink that calls findLastEpisode_helper on multiple title.

the output sequence which i need is :
start, inside, success,
start, inside, success, ...

but what i get is :
start, start, inside,success, inside, success

When i check the array lastEpisodeLink after the function has been run, it says empty which shouldn't be. How can I fix this?

Yes I have followed the answer How do I return the response from an asynchronous call? but still doesnt solves it. It would be very helpfull if you can help me fix this code. Thank you

function findLastEpisodeLink_helper(title) {

  console.log("start");
  var url;

  function onSuccess () {
    console.log('Success!');
    lastEpisodeLink.push(url);
  }

  var promise = new Promise(function(resolve, reject) {
    
    chrome.history.search(
     {
      'text': title,
      'maxResults': 1,
      'startTime': 0
     },

    function(historyItems) {

      console.log("inside");
      url = historyItems[0]["url"];
      resolve();

    });
  });
  promise.then(onSuccess);
}

The function which calls it

function findLastEpisodeLinks() {

  for(title in stringArray) { //psudo code

    findLastEpisodeLink_helper(title);
  }
}

The function which calls it is as follow, it is itself a async callback, ALL calls is being done here by it.

chrome.history.search(
   {
  'text': '',
  'maxResults': 10000,
  'startTime': 0
   },

   function(historyItems) {

      var allHistoryText = [];
      var allHistoryUrl = [];

      for(var i=0; i<historyItems.length; i++) {
        allHistoryText.push(historyItems[i]["title"]);
        allHistoryUrl.push(historyItems[i]["url"]);
      }

      // some functions

      findLastEpisodeLinks();

      displayAll(finalAllSeries);
});
Swastik Singh
  • 181
  • 1
  • 1
  • 9

3 Answers3

0

This is how I would do it,


const lastEpisodeLink = [];

function findLastEpisodeLink_helper(title) {
  return new Promise(function(resolve) {
    chrome.history.search({
      'text': title,
      'maxResults': 1,
      'startTime': 0
     },function(historyItems) {
      var url = historyItems[0]["url"];
      lastEpisodeLink.push(url);
      resolve();
    });
  });
}


async function findLastEpisodeLinks() {
  for(var title in stringArray) { 
    await findLastEpisodeLink_helper(title);
  }
}

sidthesloth
  • 1,399
  • 1
  • 11
  • 19
  • 1
    I tried the code, it doesnt solve it. The array is remains empty – Swastik Singh Sep 03 '20 at 18:14
  • yes sure here is the gist link https://gist.github.com/mightomi/3de053b58fdf4dfd82cc4485c403ddeb – Swastik Singh Sep 03 '20 at 18:27
  • I went through your code, can you add a `console.log` before `for(var obj in finalAllSeries) {` inside `findLastEpisodeLinks` function and see what is printed before the for loop executes? If the array `finalAllSeries` is populated at that time. Also, you need to add `async` before `findLastEpisodeLinks();` in line 97. Please read about how async await works. – sidthesloth Sep 03 '20 at 18:37
  • this loop `for(var obj in finalAllSeries) ` works fine I can assure you that. I cant add async or awaits in line 97 it says Uncaught SyntaxError: Unexpected identifier – Swastik Singh Sep 03 '20 at 18:59
  • using swait in line 97 says the error await only valid for async function, – Swastik Singh Sep 03 '20 at 19:11
  • Yes, that is because you can use `await` statement only inside an `async` function. That means, you have to change `function(historyItems)` to `async function(historyItems)` – sidthesloth Sep 03 '20 at 19:14
0

I think your main question is how to keep the order of the async function calls in the for-loop. For that, you will just need to await findLastEpisodeLink_helper, so that the loop waits until its promise is resolved.

async function findLastEpisodeLink_helper(title) {
  console.log('start');
  var url;

  function onSuccess() {
    console.log('Success!');
    lastEpisodeLink.push(url);
  }

  await new Promise(function (resolve, reject) {
    chrome.history.search(
      {
        text: title,
        maxResults: 1,
        startTime: 0,
      },

      function (historyItems) {
        console.log('inside');
        url = historyItems[0]['url'];
        resolve();
      },
    );
  });

  onSuccess();
}

async function findLastEpisodeLinks() {
  for (title in stringArray) {
    //psudo code
    await findLastEpisodeLink_helper(title);
  }
}

  • Hey i tried your code, the problem remains, the array is of size 0. the link to code https://gist.github.com/mightomi/12f0af3692d9dd91650122fdd4d280d9 – Swastik Singh Sep 03 '20 at 18:35
  • @SwastikSingh you are not `await`ing the `findLastEpisodeLinks` function. You are logging it right away when you run the code. – Diyorbek Sadullaev Sep 03 '20 at 18:42
  • i tried but somehow it says await only valid for async function, the code is the exact same. – Swastik Singh Sep 03 '20 at 19:09
  • @SwastikSingh you need to wrap that large statement with async function (name it `init` or `main`) and use await inside it. And, don't forget to call it) – Diyorbek Sadullaev Sep 03 '20 at 19:14
-1

Use the modern async + await syntax and Promise.all:

function search(title) {
  return new Promise(resolve => {
    chrome.history.search({
      'text': title,
      'maxResults': 1,
      'startTime': 0,
    }, results => resolve(results[0].url));
  });
}

async function findLastEpisodeLinks(titles) {
  const results = await Promise.all(titles.map(search));
  console.log(results);
}

Usage: findLastEpisodeLinks(['text a', 'text b', 'text c'])

wOxxOm
  • 65,848
  • 11
  • 132
  • 136