简体   繁体   中英

Limit calls to external api node

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM