Reputation: 361
I'm, in node and I have an array of obj {suggestion: 'text', rank: '2'}
that I want to use to make a call to bing to get the first result on each of them.
At the moment, I have managed it using a Promise.all
await Promise.all(suggestions.map(async (s, i) => await bingWebSearch(s.suggestion.replace(/\s/g, '+'), i)))
.then(r => {
suggestions.map((s, i) => console.log(`
n${i+1}. ${s.suggestion} | times suggested: ${s.rank} | url: ${s.webpage}
`))
})
.catch(e => e.message)
that will call the function bingWebSearch and assign the website URL to the obj
const bingWebSearch = async (query, i) => {
return await axios.get('https://api.bing.microsoft.com/v7.0/search?', {
headers: {
'Ocp-Apim-Subscription-Key': SUBSCRIPTION_KEY
},
params: {
count: 1,
mkt: 'en-US',
q: query
}
}).then(r => {
if (r.data.webPages) return suggestions[i].webpage = r.data.webPages.value[0].url
}).catch(e => console.log(e.message))
}
So basically, this will fire 30 calls to bing, but I am allowed only to do 3/second how I can I achieve it? I have tried with a setTimeOut, but using the async func is a bit tricky, so it did not work.
Upvotes: 0
Views: 288
Reputation: 329
here is my suggestion:
function delay(ms) {
return new Promise(function (resolve) {
setTimeout(resolve, ms);
});
}
const bingWebSearch = (query, ms) => {
return new Promise((resolve, reject) => {
delay(ms).then(() => {
axios
.get("https://api.bing.microsoft.com/v7.0/search?", {
headers: {
"Ocp-Apim-Subscription-Key": SUBSCRIPTION_KEY
},
params: {
count: 1,
mkt: "en-US",
q: query
}
})
.then(r => {
resolve(r.data.webPages.value[0].url);
})
.catch(e => {
console.log(e.message);
// this will just return an empty string as a result, if something goes wrong
resolve("");
// you can also reject and handle the exception inside calling for loop
// if more advanced error handling is required
// reject(e);
});
});
});
};
async function load() {
const requests = suggestions.map((s, i) => {
// delay each request by 400ms to avoid hitting the limit of 3 requests per second
const ms = i * 400;
return bingWebSearch(s.suggestion.replace(/\s/g, "+"), ms);
});
const res = await Promise.all(requests);
suggestions.forEach((s, i) => {
s.webpage = res[i];
console.log(`n${i + 1}. ${s.suggestion} | times suggested: ${s.rank} | url: ${s.webpage}`);
});
}
(function () {
load();
})();
I refactored bingWebSearch
a bit, to only return the result, and not directly changing the list of suggestions. Try keeping functions as self contained as possible without external dependencies.
Upvotes: 0