javascript - Node JS - 从异步函数获取数据

标签 javascript node.js asynchronous

我在 nodejs 中使用请求模块从某些网站提取数据。

let asyncFunction = () => {
    let listWeb = ['https://www.npmjs.com/package/request', 'https://www.npmjs.com/package/cheerio']
    let promiseArray = []

    listWeb.forEach(async element => {
        await requestpromise({
            url: element,
            method: "GET",
            proxy: "http://sacombank%5Cdatnq29692%3ASatureday%40123@192.168.95.100:3128",
            strictSSL: false,
            //resolveWithFullResponse: true
        })
        .then(res => {
            let $ = cheerio.load(res);
            let name = $('#top > div.w-100.ph0-l.ph3.ph4-m > h2 > span');

            name.each((ind, ele) => {
                console.log(ele.attribs.title);
                promiseArray.push(ele.attribs.title);
            });
        })
        .catch(err => {
            console.log(err);
        });
    })

    console.log(promiseArray);
}

asyncFunction()

我想从终端看到的结果是:

['request','cheerio']

但响应也像:

[]
request
cheerio

你们能帮忙修复它并解释一下 async 和 await 函数以及我的代码有什么问题吗? 非常感谢!!!

最佳答案

欢迎来到 Node.js 中 Javascript 和 http 请求的异步世界。除非在非常特定的情况下,Javascript 中的异步操作是非阻塞的,并且不会停止您的代码流。当异步操作在后台运行时,代码会继续运行。在这个特定的函数中,这意味着您的 .forEach() 循环不会等待 await 完成(因为 .forEach() 不是 promise 意识)。

而且,您的函数会在任何一个 await requestpromise() 操作完成之前返回(这就是您首先在日志中获取 [] 的原因)。因此,您不能在那里查看结果,因为尚未计算结果。

您可以通过进行一些更改来解决问题。由于您的请求是独立的,因此您可以并行运行它们并使用 Promise.all() 告诉您它们何时完成并按顺序收集结果。这也应该比尝试一次执行一个操作运行得快一点。

let asyncFunction = () => {
    let listWeb = ['https://www.npmjs.com/package/request', 'https://www.npmjs.com/package/cheerio']

    return Promise.all(listWeb.map(element => {
        return requestpromise({
            url: element,
            method: "GET",
            proxy: "http://sacombank%5Cdatnq29692%3ASatureday%40123@192.168.95.100:3128",
            strictSSL: false,
            //resolveWithFullResponse: true
        }).then(res => {
            let $ = cheerio.load(res);
            let name = $('#top > div.w-100.ph0-l.ph3.ph4-m > h2 > span');

            // get an array of title values and make that the resolved value
            // of this promise
            return name.map((ind, ele) => {
                return ele.attribs.title;
            }).get();
        })
    })).then(results => {
        console.log(results.flat());
    }).catch(err => {
        console.log(err);
    })
}

asyncFunction();

如果您想对这两个操作进行排序,则需要将 .forEach() 替换为常规的 for 语句。 for 用于暂停 await.forEach() 并不是为了在其回调中暂停 await 而构建的。这可能看起来像这样:

let asyncFunction = async () => {
    let listWeb = ['https://www.npmjs.com/package/request', 'https://www.npmjs.com/package/cheerio']
    let results = [];

    try {
        for (let element of listWeb) {
            let res = await requestpromise({
                url: element,
                method: "GET",
                proxy: "http://sacombank%5Cdatnq29692%3ASatureday%40123@192.168.95.100:3128",
                strictSSL: false,
                //resolveWithFullResponse: true
            });
            let $ = cheerio.load(res);
            let name = $('#top > div.w-100.ph0-l.ph3.ph4-m > h2 > span');

            name.each((ind, ele) => {
                results.push(ele.attribs.title);
            });
        }
        console.log(results);
    } catch(e) {
        console.log(e);
    }
}


asyncFunction()

关于javascript - Node JS - 从异步函数获取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59573118/

相关文章:

python - 使用 aiohttp 无法完全下载图像

multithreading - 带有 Jersey 的异步 REST API

javascript - 您如何设计单个 JQuery 自动完成小部件的样式?

javascript - jQuery 插件选项如何变得未定义?

node.js - PUBG 移动 api - 是否存在任何返回用户信息的 pubg 移动 api

node.js - 让 npm 重新生成 node_modules/.bin 符号链接(symbolic link)

javascript - 我怎样才能让ahoy的javascript异步函数跟踪同步

Javascript for 循环检查条件

javascript - 'chunked' 响应进入 AngularJS 后立即显示的方法是什么?

javascript - NodeJS 聊天服务器示例代码