JavaScript/Promise - 定义 promises 链接之间的超时
JavaScript/Promise - Define timeout between promises chaining
我正在使用 cheeriojs 抓取 一个站点,我需要针对几个 url 参数发出大量请求。
最小代码:
const rp = require('request-promise');
const cheerio = require('cheerio');
[1, 2, 3].forEach(element => {
url = `https://whosebug.com/q=${element}`
rp(url)
.then((html) => {
// Logic code
})
})
我想在每个请求之间设置一个超时时间,我们如何定义它?
如果要使用forEach
语句,请使用我的第一个代码。如果您不介意,请参阅我的第二个(更简单的)工作示例,该示例基于@JFord 的回答。
RunKit demo with for item of list
注意:代码已修复,可以正常工作
forEach
例子
const rp = require('request-promise')
const cheerio = require('cheerio')
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
async function forEachAsync(arr, fn) {
for (var i = 0; i < arr.length; i++) {
await fn(arr[i])
}
}
async function fetchUrls() {
await forEachAsync([55505362, 55505363, 55505364], async element => {
await sleep(2000)
console.log('been 2000 seconds')
var url = `https://whosebug.com/questions/${element}`
await rp(url)
.then(html => {
console.log(html)
})
.catch(function(e) {
console.log(e.message) // "oh, no!"
})
})
}
fetchUrls()
for item of list
例子
这是一个工作示例,基于@JFord 的回答,但额外处理了错误。
const rp = require('request-promise')
const cheerio = require('cheerio')
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
async function fetchUrls(list) {
for (const item of list) {
const html = await rp(`https://whosebug.com/q=${item}`).catch(function(e) {
console.log(e.message) // There's an error
})
console.log("html: " + html)
await sleep(2000);
}
}
fetchUrls([1,2,3])
您可以使用 forEach
的索引参数作为超时延迟的乘数
const delay = 1000
[1, 2, 3].forEach((element, i) => {
url = `https://whosebug.com/q=${element}`
setTimeout(() => {
rp(url)
.then((html) => {
// Logic code
})
}, i * delay);
})
目前所有的请求基本上都是并行的。在您可以在它们之间添加延迟之前,您必须按顺序执行它们。您可以通过 chaining 承诺来做到这一点。这很容易做到 .reduce
:
const rp = require('request-promise');
const cheerio = require('cheerio');
[1, 2, 3].reduce((p, element) => {
url = `https://whosebug.com/q=${element}`
return p
.then(() => rp(url))
.then((html) => {
// Logic code
});
}, Promise.resolve())
这构建了一个等同于
的链
rp(url1)
.then(html => ...)
.then(() => rp(url1))
.then(html => ...)
.then(() => rp(url2))
.then(html => ...)
为了增加延迟,我们定义了一个函数 returns 一个函数 returns 一个承诺在 x 毫秒后通过 setTimeout
:
解决的函数
function wait(x) {
return () => new Promise(resolve => setTimeout(resolve, x));
}
现在我们可以将它添加到我们的链中(我在这里用可运行的东西替换 rp
):
function wait(x) {
return () => new Promise(resolve => setTimeout(resolve, x));
}
[1, 2, 3].reduce((p, element) => {
const url = `https://whosebug.com/q=${element}`
return p
.then(() => Promise.resolve(url))
.then((html) => {
console.log(`Fetched ${html}`);
})
.then(wait(2000));
}, Promise.resolve())
我认为最易读的方法是使用异步函数和 promise 超时。
function sleep(millis) {
return new Promise(resolve => setTimeout(resolve, millis));
}
async function process(list) {
for (const item of list) {
const html = await rp(`https://whosebug.com/q=${item}`);
... do stuff
await sleep(1000);
}
}
我正在使用 cheeriojs 抓取 一个站点,我需要针对几个 url 参数发出大量请求。
最小代码:
const rp = require('request-promise');
const cheerio = require('cheerio');
[1, 2, 3].forEach(element => {
url = `https://whosebug.com/q=${element}`
rp(url)
.then((html) => {
// Logic code
})
})
我想在每个请求之间设置一个超时时间,我们如何定义它?
如果要使用forEach
语句,请使用我的第一个代码。如果您不介意,请参阅我的第二个(更简单的)工作示例,该示例基于@JFord 的回答。
RunKit demo with for item of list
注意:代码已修复,可以正常工作
forEach
例子
const rp = require('request-promise')
const cheerio = require('cheerio')
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
async function forEachAsync(arr, fn) {
for (var i = 0; i < arr.length; i++) {
await fn(arr[i])
}
}
async function fetchUrls() {
await forEachAsync([55505362, 55505363, 55505364], async element => {
await sleep(2000)
console.log('been 2000 seconds')
var url = `https://whosebug.com/questions/${element}`
await rp(url)
.then(html => {
console.log(html)
})
.catch(function(e) {
console.log(e.message) // "oh, no!"
})
})
}
fetchUrls()
for item of list
例子
这是一个工作示例,基于@JFord 的回答,但额外处理了错误。
const rp = require('request-promise')
const cheerio = require('cheerio')
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
async function fetchUrls(list) {
for (const item of list) {
const html = await rp(`https://whosebug.com/q=${item}`).catch(function(e) {
console.log(e.message) // There's an error
})
console.log("html: " + html)
await sleep(2000);
}
}
fetchUrls([1,2,3])
您可以使用 forEach
的索引参数作为超时延迟的乘数
const delay = 1000
[1, 2, 3].forEach((element, i) => {
url = `https://whosebug.com/q=${element}`
setTimeout(() => {
rp(url)
.then((html) => {
// Logic code
})
}, i * delay);
})
目前所有的请求基本上都是并行的。在您可以在它们之间添加延迟之前,您必须按顺序执行它们。您可以通过 chaining 承诺来做到这一点。这很容易做到 .reduce
:
const rp = require('request-promise');
const cheerio = require('cheerio');
[1, 2, 3].reduce((p, element) => {
url = `https://whosebug.com/q=${element}`
return p
.then(() => rp(url))
.then((html) => {
// Logic code
});
}, Promise.resolve())
这构建了一个等同于
的链rp(url1)
.then(html => ...)
.then(() => rp(url1))
.then(html => ...)
.then(() => rp(url2))
.then(html => ...)
为了增加延迟,我们定义了一个函数 returns 一个函数 returns 一个承诺在 x 毫秒后通过 setTimeout
:
function wait(x) {
return () => new Promise(resolve => setTimeout(resolve, x));
}
现在我们可以将它添加到我们的链中(我在这里用可运行的东西替换 rp
):
function wait(x) {
return () => new Promise(resolve => setTimeout(resolve, x));
}
[1, 2, 3].reduce((p, element) => {
const url = `https://whosebug.com/q=${element}`
return p
.then(() => Promise.resolve(url))
.then((html) => {
console.log(`Fetched ${html}`);
})
.then(wait(2000));
}, Promise.resolve())
我认为最易读的方法是使用异步函数和 promise 超时。
function sleep(millis) {
return new Promise(resolve => setTimeout(resolve, millis));
}
async function process(list) {
for (const item of list) {
const html = await rp(`https://whosebug.com/q=${item}`);
... do stuff
await sleep(1000);
}
}