1

Using this code as a reference I tried making a function which takes words as input and chops it into 32-word pieces and returns a list of the different search data:

async function singleSearch(q, cx, auth) {
   const res = await customsearch.cse.list({
     cx: cx,
     q: q,
     auth: auth,
   });
   return res.data;
 };

function search(words, apikey=process.argv[2], engineid=process.argv[3]){
   const limit = 32; //32 word limit on google search
   var searchQueries = [];
   var len = Math.ceil(words.length/limit);
   for(var i = 0; i < len; i++){
       searchQueries.push( words.slice(i*limit, (i+1)*limit).join(" ") )
   };
   var searches = []
   for(var i = 0; i < searchQueries.length; i++){
       searches.push(singleSearch(searchQueries[i], engineid, apikey).catch(console.error))
   };
   return searches
   }

a = search("Do I understand it correctly that anotherCall() will be called only when someCall() is completed? What is the most elegant way of calling them in parallel?".split(" "));
console.log(a)

This approach doesn't work and returns a Promise { <pending> }, and no matter how many await/async's or Promise.all()'s I try, I can't get it to work. What is the correct way to call the API in this case?

Expected Output:

[
    {
  kind: 'customsearch#search',
  url: {
    type: 'application/json',
    template: 'https://www.googleapis.com/customsearch/v1?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}&safe={safe?}&cx={cx?}&sort={sort?}&filter={filter?}&gl={gl?}&cr={cr?}&googlehost={googleHost?}&c2coff={disableCnTwTranslation?}&hq={hq?}&hl={hl?}&siteSearch={siteSearch?}&siteSearchFilter={siteSearchFilter?}&exactTerms={exactTerms?}&excludeTerms={excludeTerms?}&linkSite={linkSite?}&orTerms={orTerms?}&relatedSite={relatedSite?}&dateRestrict={dateRestrict?}&lowRange={lowRange?}&highRange={highRange?}&searchType={searchType}&fileType={fileType?}&rights={rights?}&imgSize={imgSize?}&imgType={imgType?}&imgColorType={imgColorType?}&imgDominantColor={imgDominantColor?}&alt=json'},
    ...
 },
...
]
hhhhhhhhhn
  • 31
  • 3
  • I wanted to inquire if you're interested in doing some work, I found one of your repos online (hookjs) and I was wondering if you'd be interested in getting in contact, if so, reply to the issue I opened there, thanks! Hope this doesn't appear as spam, I just didn't know how else to try to contact you since there isn't an email and your website is down. – Kevin Danikowski Mar 02 '21 at 15:49

2 Answers2

1

Since the singleSearch async function returns a promise, you need to use then to get the result of the search and then push it to the searches array.

searches.push(singleSearch(searchQueries[i], engineid, apikey).catch(console.error))

Checkout this answer on Stackoverflow.

Khaled
  • 93
  • 2
  • 9
1

The problem is you are trying to do asynchronus in loop which doesn't work the way you are expecting. You need to either use Promise.all or use for..of loop with await. You can do Promise.all way like this.

async function singleSearch(q, cx, auth) {
  const res = await customsearch.cse.list({
    "cx": cx,
    "q": q,
    "auth": auth
  });
  return res.data;
}

function search(words, apikey = process.argv[2], engineid = process.argv[3]) {
  const limit = 32; // 32 word limit on google search
  const searchQueries = [];
  const len = Math.ceil(words.length / limit);
  for (var i = 0; i < len; i++) {
    searchQueries.push(words.slice(i * limit, (i + 1) * limit).join(" "));
  }

  return Promise.all(searchQueries.map(query => {
    return singleSearch(query, engineid, apikey).catch(console.error);
  }));
}

(async () => {
  const a = await search("Do I understand it correctly that anotherCall() will be called only when someCall() is completed? What is the most elegant way of calling them in parallel?".split(" "));
  console.log(a);
})();


Ashish Modi
  • 7,529
  • 2
  • 20
  • 35