node.js - 如何使用promise在循环后获取数据
问题描述
我正在处理一个异步问题。我正在制作一个网络抓取工具,在抓取网络之后,我需要将数据放入我的 MongoDB 数据库中。我需要将它发送到前端,但是由于我有一个循环元素,所以我不能放在res.json()
里面,因为它会给出一个错误(你只能在res.json())
.
我被困在这里。我以前使用过承诺,但这很令人困惑。
router.get('/scrape', (req, res) => {
request('http://www.nytimes.com', function test(error, response, html) {
const $ = cheerio.load(html);
// An empty array to save the data that we'll scrape
const results = [];
$('h2.story-heading, p.summary').each(function(i, element) {
const link = $(element)
.children()
.attr('href');
const title = $(element)
.children()
.text();
const summary = $(element)
.children()
.text();
const data = {
title: title,
link: link,
summary: summary,
};
articles
.create(data)
.then((resp) => results.push(resp))
// .then((resp) => Promise.resolve(results)) //
// .then((jsonDta ) => res.json(jsonData)) // error you can only give response once.
.catch((err) => reject(err));
});
console.log(results); // empty array
res.json(results)// empty
});
});
我的计划是:
- 抓取网站(循环元素)
- 然后保存到 MongoDB 中(将数据推送到数组中)
- 然后在循环之后将其传递给前端。
我需要将查询方法create...
放在循环中,因为我需要每个数据都有一个 id。
解决方案
与其尝试直接累积结果,不如将其中包含的元素映射$('h2.story-heading, p.summary')
到一个 promise 数组,然后使用Promise.all()
. 您想要的结果将由Promise.all(...).then(...)
.
router.get('/scrape', (req, res) => {
request('http://www.nytimes.com', function test(error, response, html) {
const $ = cheerio.load(html);
const promises = $('h2.story-heading, p.summary')
.get() // as in jQuery, .get() unwraps Cheerio and returns Array
.map(function(element) { // this is Array.prototype.map()
return articles.create({
'title': $(element).children().text(),
'link': $(element).children().attr('href'),
'summary': $(element).children().text()
})
.catch(err => { // catch so any one failure doesn't scupper the whole scrape.
return {}; // on failure of articles.create(), inject some kind of default object (or string or whatever).
});
});
// At this point, you have an array of promises, which need to be aggregated with Promise.all().
Promise.all(promises)
.then(results => { // Promise.all() should accept whatever promises are returned by articles.create().
console.log(results);
res.json(results);
});
});
});
如果您希望任何单个故障都破坏整个刮擦,请省略catch()
and addcatch()
到Promise.all().then()
链中。
笔记:
对于
.get()
(和大多数其他方法),jQuery 文档比Cheerio 文档更好(但要小心,因为 Cheerio 是 jQuery 的精简版本)。您在任何时候都不需要
new Promise()
. 您需要的所有承诺都由articles.create()
.
推荐阅读
- python - 获取 TypeError: unhashable type: 'dict_keys' in jupyter notebook
- python - 如果值与给定字典中的键相等,我如何将第一个键的值附加到所述值的键
- react-native - React Native 快速滚动列表视图
- java - 在android中上传图像uisng预签名AWS URL
- c# - 读取 Textfile 函数时发生 IOException ReadtoEnd
- shopware - 从现有插件中分离代码 - Shopware
- angular - Angular 使用 - ngDoCheck 监听数字属性(不是 @Input)的值变化?
- java - 当最小值可以是android中的签名数字时,如何修复编辑文本的最小值?
- file - 使用 VBS 替换多个文本文件中的文本
- swift - 多个工作表(isPresented :) 在 SwiftUI 中不起作用