【问题标题】:Node.js async - build object from loop, then do something with objectNode.js 异步 - 从循环构建对象,然后对对象执行某些操作
【发布时间】:2015-08-02 12:30:51
【问题描述】:

我正在尝试运行一个函数,一旦该函数完成,然后运行另一个函数。第一个函数读取一个 CSV 文件,发出一个 GET 请求,然后构建一个对象。第二个函数使用新创建的对象来创建一个新的 CSV 文件。

我遇到的问题是新的 CSV 文件是在 GET 请求完成之前创建的。

我正在使用 async.parallel 设置流程,但无法正确获取逻辑。

我很想知道我做错了什么并更好地了解 node 是如何看待这些任务的。

// Require
var request = require('request');
var fs = require('fs');
var json2csv = require('json2csv');
var csv = require('csv');
var async = require('async');

// Params
var emailHunter_apiKey = '0000';
var emails = [];
var fields = ['email'];
var i = 0;

// Start
async.parallel([
        function(callback){
            setTimeout(function(){
                var file = fs.readFileSync('file.csv');
                csv.parse(file, {delimiter: ','}, function (err, data) {
                    for (var key in data) {
                        if (i < 5) {
                            if (data.hasOwnProperty(key)) {
                                var h = data[key];
                                if (h[5] != '') {
                                    var url = h[5];
                                    url = url.replace('//', '');
                                    url = url.replace('www.', '');
                                    request('https://api.emailhunter.co/v1/search?domain=' + url + '&api_key=' + emailHunter_apiKey + '', function (error, response, body) {
                                        if (!error && response.statusCode == 200) {
                                            var json = JSON.parse(body);
                                            for (var subObj in json) {
                                                if (json.hasOwnProperty(subObj) && subObj == 'emails') {
                                                    var emailObj = json[subObj];
                                                    for (var key in emailObj) {
                                                        var email = {
                                                            'email': emailObj[key]['value']
                                                        };
                                                        emails.push(email);
                                                    }
                                                }
                                            }
                                        }
                                    });
                                }
                            }
                        }
                        i++;
                    }
                });
                callback(null, emails);
            }, 200);
            console.log(emails);
        }
    ],
    function(err, results){
        json2csv({data: results, fields: fields}, function (err, csv) {
            if (err) console.log(err);
            fs.writeFile('export.csv', csv, function (err) {
                if (err) throw err;
                console.log('file saved');
            });
        });
        console.log(results);
    });

【问题讨论】:

  • 首先,您使用 async.parallel 错误,因为您的第一个参数中只有 1 个函数。它应该采用一组(多个)函数。其次,我认为 Promises 可能更适合您的需求,请查看这些。基本上,您依赖于 request (这是异步的)的多次执行完成,因此您需要对其进行承诺并检查所有承诺何时已解决。当您发现 Promise 时,您将了解更多有关它的信息。最后,为了便于阅读,您的代码是 callback-hell which you should avoid
  • 感谢您浏览此内容。我肯定在尝试围绕回调结构并了解节点的想法/工作方式。这对于 promise 的建议也是有意义的。再次感谢您的帮助!

标签: node.js loops csv asynchronous


【解决方案1】:

正如 laggingreflex 提到的,您错误地使用了异步。

首先,您应该构建一个要并行执行的函数数组。然后使用 async 来执行它们。

此外,您的回调会立即执行,因为 csv.parse() 是一个异步函数。因此节点立即触发它,然后执行回调()。您需要在 parse() 中移动回调。

试试这个...

// Params
var emailHunter_apiKey = '0000';
var emails = [];
var fields = ['email'];
var i = 0;
var functionsToRunAsync = [];

var file = fs.readFileSync('file.csv');
csv.parse(file, {delimiter: ','}, function (err, data) {
    for (var key in data) {
        if (i < 5) {
            if (data.hasOwnProperty(key)) {
                var h = data[key];
                if (h[5] != '') {
                    var url = h[5];
                    url = url.replace('//', '');
                    url = url.replace('www.', '');

                    // add a new function to an array, to be executed later
                    functionsToRunAsync.push(function(callback) {
                        request('https://api.emailhunter.co/v1/search?domain=' + url + '&api_key=' + emailHunter_apiKey + '', function (error, response, body) {
                            if (!error && response.statusCode == 200) {
                                var json = JSON.parse(body);
                                for (var subObj in json) {
                                    if (json.hasOwnProperty(subObj) && subObj == 'emails') {
                                        var emailObj = json[subObj];
                                        for (var key in emailObj) {
                                            var email = {
                                                'email': emailObj[key]['value']
                                            };
                                            emails.push(email);

                                            // callback to tell async this function is complete
                                            callback()
                                        }
                                    }
                                }
                            } else {
                                // callback to tell async this function is complete
                                callback
                            }
                        });
                    });

                }
            }
        }
        i++;
    }

    // now that we have all of the functions in an array, we run them in parallel
    async.parallel(

        functionsToRunAsync,

        function(err, results) {    // all async functions complete
            json2csv({data: results, fields: fields}, function (err, csv) {
                if (err) console.log(err);
                fs.writeFile('export.csv', csv, function (err) {
                    if (err) throw err;
                    console.log('file saved');
                });
            });
            console.log(results);
    });
});

【讨论】:

  • 非常感谢您浏览该内容。这更有意义并且有效。我喜欢并行函数数组的想法。几天前我刚开始使用node,正在编写一些小脚本来学习。
猜你喜欢
  • 2017-05-16
  • 2016-10-25
  • 2020-10-03
  • 1970-01-01
  • 2017-06-17
  • 2014-10-10
  • 2012-02-25
  • 2017-09-26
  • 2016-01-21
相关资源
最近更新 更多