【问题标题】:Performing async function on each element in array?对数组中的每个元素执行异步函数?
【发布时间】:2014-02-15 16:35:34
【问题描述】:

所以我有一个 URL 数组

我想从每个中提取 html(我正在使用 restler node.js 库)

然后通过 jquery 选择一些数据进行操作(为此我使用cheerio node.js 库)

我的代码可以工作,但是无论有多少 URL,都会复制提取的数据。 我在 Node 中执行此操作,但怀疑这是我不太了解的通用 Javascript 问题。

url.forEach(function(ugh){
    rest.get(ugh).on('complete', function(data) {
        $ = cheerio.load(data);
        prices.push($(".priceclass").text());
        //i only want this code to happen once per item in url array
        //but it happens url.length times per item
        //probably because i don't get events or async very well
    });
});

所以如果 'url' 数组中有 3 个项目,那么包含我想要的数据的 'prices' 数组将有 9 个项目。我不想要的

--编辑:

添加了一个计数器来验证“完成”回调是否对每个数组项执行了数组长度的次数。

x=0;
url.forEach(function(ugh){
    rest.get(ugh).on('complete', function(data) {
        var $ = cheerio.load(data);
        prices.push($(".priceclass").text());
        console.log(x=x+1);
    });
});

控制台输出 1 2 3 4 5 6 7 8 9

我在想我可能做错了。我一直在尝试将一些数字推送到数组中,然后在回调之外对该数组进行一些操作。

无论如何,>1个restler eventlisteners似乎根本不会一起工作。

也许改写问题会有所帮助: 我将如何抓取一些 URL,然后对这些数据采取行动?

目前正在通过已消失的node.io library 中的代码研究请求和异步库

【问题讨论】:

  • 错字:url.forEach() prices.push($(".priceclass").text();
  • 你有一个不匹配的(
  • 哦-我在粘贴时修改了一些代码。工作代码中没有拼写错误。
  • 如果您使用 jquery,$ = cheerio.load(data); 是个坏主意。请点击您问题中标签列表下方的“编辑”并修正错别字。
  • "9 items" 在结果数组中听起来像 rest.get(ugh).on 函数中的错误(不是因为您的使用)。您能否确认“完成”回调被调用了 9 次——每个 3 个 url 调用 3 次?除此之外,我建议var $ = …

标签: javascript arrays node.js


【解决方案1】:

如果你使用 ES6+ 和我假设你这样做的节点,scramjet 非常适合这个问题:

我如何抓取一些 URL,然后对这些数据采取行动?

安装包:

npm install scramjet node-fetch --save

Scramjet 适用于流 - 它会读取您的 url 列表并使每个 url 成为一个流,您可以像使用 Array 一样简单地使用它。 node-fetch 是一个遵循标准 Fetch Web API 的简单节点模块。

一个简单的例子,它也从文件中读取 url,假设你每行存储一个:

const {StringStream} = require("scramjet");
const fs = require("fs")
const fetch = require("node-fetch");

fs.createReadStream(process.argv[2])     // open the file for reading
    .pipe(new StringStream())            // redirect it to scramjet stream
    .split("\n")                         // split line by line
    .map((url) => fetch(url))            // get the URL from the endpoint
    .map((resp) => JSON.parse(resp))     // parse the response
    .toArray()                           // accumulate the data into an Array
    .then(
         (data) => doYourStuff(data),    // do the calculations
         (err) => showErrorMessage(data)
    )

由于 scramjet 的工作方式,您无需担心错误处理(所有错误都会自动捕获)和管理同时请求。如果您可以通过 url 解析文件 url,那么您还可以提高内存和资源效率 - 因为它不会准备好并尝试一次获取所有项目,但它会并行执行一些工作。

scramjet docs 中有更多示例和完整的 API 描述。

【讨论】:

    猜你喜欢
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 2016-04-06
    • 2020-11-17
    相关资源
    最近更新 更多