如何阻止功能,直到前一个功能完成?的NodeJS

arc*_*ect 6 node.js

有一个动态值可能从小到大的for循环,我想确保在下一个调用开始之前完成一次搜索调用.我怎么做?我已经阅读了有关process.nextTick和setImmediate的内容,但我不确定如何在此上下文中使用它.

function search(x) {
      dns.resolve(x, function (err, addresses) {
           if (!err) {
                res.send("bad");
           } else {
                res.send("good");
           }
      });
}

for(a = 0; a < queries.length; a++) {
    query = queries[a];
    search(query);
}
Run Code Online (Sandbox Code Playgroud)

go-*_*leg 6

有一些库可以帮助您组织异步代码的执行. 异步是我使用的,它的eachSeries()在这里很有用:

function search(x,callback) {
  dns.resolve(x, function (err, addresses) {
    if (!err) {
      res.send("bad");
    } else {
      res.send("good");
    }
    callback(err);
  });
}

async.eachSeries(queries,
  function(query,callback) {
    search(query,callback);
  },
  function(err) {
    if(err) {
      console.log("we had an error");
    }
  }
);
Run Code Online (Sandbox Code Playgroud)

需要注意的是异步将尽快迭代的一个具有错误调用最终回调,所以如果你不想停在那里,你将需要调用callback()search()替代callback(err).

更新(不使用库):

如果您不想使用库,可以自己实现,如下所示:

function searchInternal(queries, idx, callback) {
  if(idx === queries.length) {
    callback();
    return;
  }

  dns.resolve(queries[idx], function (err, addresses) {
    if (!err) {
      res.send("bad");
    } else {
      res.send("good");
    }
    searchInternal(queries, idx+1, callback);
  });
}

function searchAll(queries, callback) {
  searchInternal(queries, 0, callback);
}

searchAll(queries, function() {
  console.log("all done now");
});
Run Code Online (Sandbox Code Playgroud)

注意,此代码未经过测试,可能不是最佳实现,但这就是我们使用库的原因.

  • @EhevuTov:它的异步意味着`searchAll`之后的代码将在所有搜索完成之前执行,但实际搜索_appear_同步因为我在前一个回调中调用下一个`searchInternal`(即在之后完成).我喜欢你的`EventEmitter`方法! (2认同)

Ehe*_*Tov 3

我通常只使用事件发射器来使其全部同步,这样我仍然可以在异步环境思维模式下工作。在下面的代码中,每当 DNS 解析完成时,它都会生成一个由搜索函数侦听的事件,并让它知道要启动新的搜索。另外,您还可以学习如何创建自己的事件发射器,这非常棒。

如果要使其对特定大小的域名数组异步,可以创建一个分母变量并使用模运算符以块的形式异步发送,并且仅在模数达到时触发同步事件(以清除异步缓冲区) 0。

// program that uses event emitters to create sync code in an async env

var dns = require('dns')                                //dns from core
var eventEmitter = require('events').EventEmitter       //Event Emitter from core

var ee = new eventEmitter;      //make an Event Emitter object

var queries = ['yahoo.com','google.com','james.com'];

ee.on('next', next_search);     //create a listener for an event we define

// our listening function that executes on our defined 'next' event
function next_search() {
        search(queries[a]);
        if(queries.length == a) process.exit(0);
        ++a;
}

// the actual search function that uses DNS
function search(x) {
        dns.resolve(x, function (err) {
                if (!err) {
                        //res.send("bad");
                        console.log('bad: ' + x)
                        ee.emit('next')
                } else {
                        //res.send("good");
                        console.log('good: ' + x)
                        ee.emit('next')
                }
        });
}


// global variable to keep track of our name queue length
var a = 0;

// kick it all off
next_search()
Run Code Online (Sandbox Code Playgroud)