素材牛VIP会员
请教关于node异步循环的问题
 wa***ao  分类:Node.js  人气:984  回帖:2  发布于6年前 收藏

代码很简单,如下:

var find;
data.some(function(ip) {
    client.sismember(url+':ip', ip, function(err, mem) {
        !mem && (find = ip);
        console.log('redis:' + find);
    });

    console.log(find);
    return find;
});

原理很简单:

  • 我先some循环一个IP数组
  • 如果数组中的IP不存在redis中,我就将find赋值为当前IP
  • 如果循环过程中找到了IP,我就跳出循环,不再一直查询redis

结果,代码中有两个console:

  • 先循环数组数据,find一直是undefined,因此不会跳出循环
  • 之后执行所有redis查询结果,并重复给find复制,并打印出来

问题:

  • 首先结果不是我想要的
  • 效率差,我循环100条就查询100次redis

请问如何解决?

 标签:node.js

讨论这个帖子(2)垃圾回帖将一律封号处理……

Lv1 新人
he***21 UI设计师 6年前#1
  1. 安装万能的async:sudo npm install async
  2. 把代码改成:
var async = require('async');

...

async.detect(
  data, 
  function(ip, cb) {
    client.sismember(url+':ip', ip, function(err, mem) {
        console.log('redis:' + find);
        cb(!mem);
    });
  },
  function(result) {
    find = result;
    console.log(find);
});

可以看下github上async的文档。

Lv1 新人
何***孽 软件测试工程师 6年前#2

用q.js的解决方案

npm i q

var Q = require('q');
function find (data, url, timeout) {
    var deferred = Q.defer();
    var n = data.length;
    data.forEach(function (ip) {
        Q.ninvoke(client, 'sismember', url + ':ip', ip)
            .then(function (ret) {
                if(ret) {
                    deferred.resolve(ip);
                } else if (--n <= 0) {
                    deferred.reject(new Error('Not found!'));
                }
            });
    });
    return Q.timeout(defered.promise, timeout);
}
//以上只用写一次,以下是使用方法
find(data, url, 1000)
    .then(function (ip) {
        //成功找到
        console.log('redis:' + find);
    }).fail(function (reason) {
        //没找到或超时
    });
 文明上网,理性发言!   😉 阿里云幸运券,戳我领取