【问题标题】:How to wait for each iteration in for loop and return response as API response in nodeJS如何在for循环中等待每次迭代并在nodeJS中将响应作为API响应返回
【发布时间】:2018-02-27 20:42:40
【问题描述】:

我正在使用 for 循环遍历元素数组并在 for 循环内调用具有不同参数的相同函数。这是我的代码:

exports.listTopSongs = function(query) {
    return new Promise(function(resolve, reject) {
        var str = query.split(","), category,
        for(var i=0; i<str.length; i++) {
           sampleFn(str[i], 'sample', resolve, reject);
        }
    });
};

function sampleFn(lang, cat, resolve, reject) {
        client.on("error", function (err) {
            console.log(err);
            var err = new Error('Exception in redis client connection')
            reject(err);                                
        });
        client.keys(lang, function (err, keys){
            if (err) return console.log(err);
            if(keys.length != 0) {
                client.hgetall(keys, function (error, value) {
                    var objects = Object.keys(value);
                    result['title'] = lang;
                    result[cat] = [];
                    var x =0;
                    for(x; x<objects.length; x++) {
                        var val = objects[x];
                            User.findAll({attributes: ['X', 'Y', 'Z'],
                                where: {
                                    A: val
                                }
                            }).then(data => {
                                if(data != null) {
                                    //some actions with data and stored it seperately in a Json array
                                    if(result[cat].length == objects.length) {
                                        resolve(result);
                                    }
                                } else {
                                    console.log(""+cat+" is not avilable for this value "+data.dataValues['X']);
                                }
                            });
                    }
               });
         });
   }

这里它不会等待第一次迭代完成。它只是在完成第一次迭代功能之前异步运行。我需要将结果作为结果返回:[{ 1, 2}, {3,4}]。但它无缝运行并在完成所有操作之前返回空对象或仅返回一个对象。如何解决。

我使用了节点异步循环。但它使用下一个,我无法在使用该包时发送我的参数。请帮帮我

【问题讨论】:

  • 检查“aync”包。它有许多使 for 循环同步运行的功能。
  • 你使用的是哪个node js版本?
  • 我使用的是节点 8.4.0
  • 好的,@ShubhamJain 会尽力让你知道

标签: javascript node.js asynchronous nodes node-modules


【解决方案1】:

Async 提供了允许这样做的控制流方法。

使用async.each

async.each(openFiles, function(file, callback) {

    // Perform operation on file here.
    console.log('Processing file ' + file);

    if( file.length > 32 ) {
      console.log('This file name is too long');
      callback('File name too long');
    } else {
      // Do work to process file here
      console.log('File processed');
      callback();
    }
}, function(err) {
    // if any of the file processing produced an error, err would equal that error
    if( err ) {
      // One of the iterations produced an error.
      // All processing will now stop.
      console.log('A file failed to process');
    } else {
      console.log('All files have been processed successfully');
    }
});

【讨论】:

    【解决方案2】:

    如果您不想使用库,可以自己编写代码。这也会很有启发性。我接受了您的问题并编写了一个虚拟异步循环:

    function listTopSongs(query) {
        return new Promise(async(resolve, reject) => { //add async here in order to do asynchronous calls
            const str = query.split(",") //str is const, and the other variable was not used anyway
            
            for( let i = 0;i < str.length; i++) {
                const planet = await sampleFn(str[i], 'sample', resolve, reject)
                console.log(planet)
            }
        });
    };
    
    function sampleFn(a, b, c, d) {
        return fetch(`https://swapi.co/api/planets/${a}/`)
            .then(r => r.json())
            .then(rjson => (a + " : " + rjson.name))
    }
    
    listTopSongs("1,2,3,4,5,6,7,8,9")

    我使用了一些虚拟的星球大战 API 来伪造一个长期承诺,但它应该适用于您的 sampleFn。小心,如果你有像示例中那样的网络调用,它会非常非常慢。

    编辑:我运行了你的代码,发现有一些错误:你的承诺中没有解决,所以它不是一个 thenable (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve see thenable )

    这是一个完整的工作代码。好的部分:不需要库,没有依赖项。

    //for node.js, use node-fetch :
    //const fetch = require("node-fetch")
    
    function listTopSongs(query) {
        return new Promise(async(resolve, reject) => { //add async here in order to do asynchronous calls
            const str = query.split(",") //str is const, and the other variable was not used anyway
            const planets = []
            for (let i = 0; i < str.length; i++) {
                const planet = await sampleFn(i + 1, str[i], resolve, reject)
                planets[i] = planet
                console.log(planet)
            }
            resolve(planets)
        });
    };
    
    function sampleFn(a, b, c, d) {
        return fetch(`https://swapi.co/api/planets/${a}/`)
            .then(r => r.json())
            .then(rjson => (a + b + " : " + rjson.name))
    }
    
    listTopSongs("a,b,c,d").then(planets => console.log(planets))

    【讨论】:

    • 我无法将我的 json 数组从函数 sampleFn 返回到 listTopSongs
    【解决方案3】:

    由于你使用的是promise,你可以做这样的事情

    exports.listTopSongs = function(query) {
        return Promise.resolve(true).then(function(){
            var str = query.split(",");
            var promises = str.map(function(s){
                return sampleFn(str[i], 'sample');
            });
            return Promise.all(promises);
        }).then(function(results){
           //whatever you want to do with the result
        });
    };
    

    为此,您必须将 sampleFn 更改为不依赖外部解析和拒绝函数。我看不出使用外部解决和拒绝的原因。为什么不使用 Promise.Resolve, Promise.Reject;

    【讨论】:

      猜你喜欢
      • 2019-07-18
      • 1970-01-01
      • 2017-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-07
      • 2018-08-04
      • 1970-01-01
      相关资源
      最近更新 更多