对使用异步函数编程完全陌生。node.js也是新的,这可能会增加我的问题。我读了很多书,并不断地遇到类似的问题,似乎我正在随机地让异步代码的某些部分工作,而其他部分则不起作用。
本质上,我正在搜索一个音乐站点,删除所有的结果(scraper_start.js),然后将其发送到scrape_individual.js收集数据。它目前能够获得所有的数据,但当它下载专辑艺术,它进入“太晚”。
图像确实被记录到控制台,但只有在信息被返回之后。此外,如果你有任何好的资源来学习异步编程,请分享它们-我还没有找到一个好的,干净的网站,并进入足够大的例子,他们变得现实(例如多个异步函数一次工作,有时相互依赖)。请批评我的代码以及-我正在努力学习!
文件scraper_start.js:
const rp = require('request-promise');
const cheerio = require('cheerio');
const scrape = require('./scrape_individual.js');
const base_url = 'https://www.test.ca';
const url = 'https://www.test.ca/search?mysearchstring';
rp(url)
.then(function(html)
{
const $ = cheerio.load(html);
var results = []
var hits = $('h3 > a').length;
console.log("TOTAL HITS: " + hits);
results = $('h3 > a').map(function(i,v){ return $(v).attr('href'); }).get()
return Promise.all(
results.map(function(url)
{
return scrape(base_url + url);
})
);
})
.then(function(my_data)
{
console.log(my_data);
});文件scrape_individual.js:
const rp = require('request-promise');
const cheerio = require('cheerio');
var info = {}
const scrape = function(url)
{
return rp(url)
.then(function(html)
{
const $ = cheerio.load(html);
if (!html.includes('contentType = "Podcast"'))
{
info = {
title: $('h2.bc-heading:first').text(),
img3: null};
img_data($('.bc-image-inset-border').attr('src'))
.then(function(v)
{
console.log(v);
info.img3 = v; // Log the value once it is resolved
})
.catch(function(v) {
});
return info;
}
})
};
function img_data(src)
{
return new Promise(function(resolve, reject)
{
const { createCanvas, loadImage } = require('canvas');
loadImage(src).then((image) =>
{
const canvas = createCanvas(image.width, image.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
resolve(canvas.toDataURL());
});
});
}
module.exports = scrape;更新:带有ASYNC /等待的新代码
scraper_start.js:
const rp = require('request-promise');
const cheerio = require('cheerio');
const scrape = require('./scrape_individual.js');
const base_url = 'https://www.test.ca';
const url = 'https://www.test.ca/search?mysearchstring';
var data = [];
async function get_links(url)
{
let html = await rp(url);
const $ = cheerio.load(html);
var results = [];
var hits = $('h3 > a').length;
console.log("TOTAL HITS: " + hits);
hrefs = $('h3 > a').map(function(i,v){ return $(v).attr('href'); }).get()
await Promise.all(hrefs.map(async (href) =>
{
let data_single = await scrape.scrape_book3(base_url + href);
data.push(data_single);
}));
//QUESTION AREA 1: This data works great with all info.
console.log(data);
return data
}
get_links(url);
//QUESTION AREA 2: This data gets printed before getting the actual data returned.
console.log(data);scrape_individual.js:
const rp = require('request-promise');
const cheerio = require('cheerio');
var info = {}
//scrape2(url)
module.exports.scrape_individual = scrape2;
async function scrape2(url)
{
let html = await rp(url);
const $ = cheerio.load(html);
if (!html.includes('contentType = "Podcast"'))
{
let my_image = await img_data($('.bc-image-inset-border').attr('src'));
info = {title: $('h2.bc-heading:first').text(),
img3: my_image};
//console.log(info);
return info;
}
}
async function img_data(src)
{
const { createCanvas, loadImage } = require('canvas');
let image = await loadImage(src);
const canvas = createCanvas(image.width, image.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
//console.log(canvas.toDataURL());
return canvas.toDataURL();
}这段代码现在运行得很好。也更容易理解。请随意批评,因为我正试图掌握这一点。我现在的问题更多的是一个普通的编码问题。
在最终结果(数据)结束的scraper_start.js中,我用“问题区域1”和“问题区域2”标记了两个注释
问题区域1:工作完全正常,因为它位于异步函数的第2区:异步函数之外,还没有返回对象,因为没有什么可说的等待。有什么办法让它等待吗?
我的问题很有说服力。据我所知,由于它不在异步函数中,所以我不能使用它。这是否意味着,如果我想维护一个重要的顺序,我的所有代码都需要处于函数中吗?什么是最佳实践?为什么不将每个函数调用为异步呢?
编辑:修复排版edit2:添加ASYNC /等待修改
发布于 2022-01-28 23:05:07
问题区域2在捕获数据之前返回,因为您告诉JS最后一个函数没有等待任何人,所以它是同步运行的。但事实是,它实际上是在等待某个人,它在等待get_links()
因此,打印数据的一种方法是:
async printer(){
const returnedData = await get_links(URL);
console.log(returnedData)
}
printer();如果您想使用从异步函数返回的数据,您需要使用wait调用它,这样JS就知道在继续之前它需要等待已解决的或拒绝的承诺,否则它将返回一个Promise<pending>。所有的人都在等待需要在异步中。一开始,听起来像是一个无穷无尽的循环,但实际上并非如此。
例如,在我们的示例中,您不需要任何其他异步来调用打印机()(因为没有其他函数依赖于这个函数),我希望它是有意义的,但在开始时承诺需要一些时间才能理解它们。在我看来,异步/等待是理解承诺的一种祝福,一旦你意识到它以及它们是如何运作的,你就能更好地理解决心/拒绝的方式。
https://stackoverflow.com/questions/70898982
复制相似问题