Javascript Promise.all in Node.js不使用映射和异步调用阻塞函数调用

Javascript Promise.all in Node.js不使用映射和异步调用阻塞函数调用,javascript,node.js,promise,Javascript,Node.js,Promise,我编写了一个小模块与Zookeeper对话,以获取服务端点列表。 除了返回端点列表的部分之外,其他部分都可以正常工作。在模块中,我公开了一个函数,该函数应该返回一个端点数组,通过调用getData(从模块节点zookeeper客户端)获得的端点数组的次数与zookeeper上特定路径中的子节点的次数相同。我尝试将数组映射和Promise.all组合起来调用getData x次,但我的函数在Promise.all之前返回,并在调用方以“undefined”变量结尾。下面是我的代码片段: zooke

我编写了一个小模块与Zookeeper对话,以获取服务端点列表。 除了返回端点列表的部分之外,其他部分都可以正常工作。在模块中,我公开了一个函数,该函数应该返回一个端点数组,通过调用getData(从模块节点zookeeper客户端)获得的端点数组的次数与zookeeper上特定路径中的子节点的次数相同。我尝试将数组映射和Promise.all组合起来调用getData x次,但我的函数在Promise.all之前返回,并在调用方以“undefined”变量结尾。下面是我的代码片段:

zookeeper.js

...
const getData = (entry) => {
  return new Promise(function(resolve, reject) {
    client.getData(
      "/application/agent/" + entry,
      function (error, data, stat) {
        if (error) {
          console.log(error);
          reject(error);
        } else {
          console.log('getData resolve %s',data.toString('utf8'));
          resolve(data.toString('utf8'));
        }
      });
  });
};
...
function agentsEndpoint() {
  console.log('Begin agentsEndpoint...');
  var requests = agentList.map(getData);
  console.log('requests: %s', requests);
  var results = Promise.all(requests);
  console.log('results: %s', results);
  results.then((endpoints) => {
    return endpoints;
  });
  console.log('...agentsEndpoint return.');
}

module.exports = { agentsEndpoint };
...
const zk = require('./zookeeper.js');
zk.client.connect();

setInterval(listEndpoints,5000, zk);
function listEndpoints(zk) {
  console.log('Calling agentsEndpoint: %s',zk.agentsEndpoint());
}
...
main.js

...
const getData = (entry) => {
  return new Promise(function(resolve, reject) {
    client.getData(
      "/application/agent/" + entry,
      function (error, data, stat) {
        if (error) {
          console.log(error);
          reject(error);
        } else {
          console.log('getData resolve %s',data.toString('utf8'));
          resolve(data.toString('utf8'));
        }
      });
  });
};
...
function agentsEndpoint() {
  console.log('Begin agentsEndpoint...');
  var requests = agentList.map(getData);
  console.log('requests: %s', requests);
  var results = Promise.all(requests);
  console.log('results: %s', results);
  results.then((endpoints) => {
    return endpoints;
  });
  console.log('...agentsEndpoint return.');
}

module.exports = { agentsEndpoint };
...
const zk = require('./zookeeper.js');
zk.client.connect();

setInterval(listEndpoints,5000, zk);
function listEndpoints(zk) {
  console.log('Calling agentsEndpoint: %s',zk.agentsEndpoint());
}
...
这里是控制台输出:

Begin agentsEndpoint...
requests: [object Promise],[object Promise]
results: [object Promise]
...agentsEndpoint return.
Calling agentsEndpoint: undefined
getData resolve 10.0.0.8/getEndpoint
getData resolve 10.0.0.10/getEndpoint
我的预期行为是,函数应该在行结果处等待。然后((端点)=>{对于要解析的结果承诺,但正如您在控制台输出中看到的,它解析要晚得多

我错过了什么

console.log('Calling agentsEndpoint: %s',zk.agentsEndpoint());
你不能返回任何东西

function agentsEndpoint() {
  ...
  console.log('...agentsEndpoint return.');
}
所以
调用代理endpoint:undefined
是有效答案

您应该以异步方式使用
agentsEndpoint

您可以使用callback、promise或async/wait

见示例:

function agentsEndpoint() {
    console.log('Begin agentsEndpoint...');
    var requests = agentList.map(getData);
    console.log('requests: %s', requests);
    var results = Promise.all(requests);
    console.log('results: %s', results);
    return results;
}

function listEndpoints(zk) {
 zk.agentsEndpoint().then(endpoints => console.log('Calling agentsEndpoint: %s', endpoints);
}

您遇到的问题的核心是
agentsEndpoint
正在执行异步操作,但它没有返回任何内容。为了知道函数的异步部分何时完成,您也需要从该函数返回一个承诺,就像
getData
。然后调用方将收到该承诺,并可以在恩,它解决了。没有
控制台的基本思想。日志将如下所示:

在zookeeper.js中==>

const agentsEndpoint = () => Promise.all(agentList.map(getData));
在main.js中==>

function listEndpoints(zk) {
    zk.agentsEndpoint()
    .then(elements => console.log('Calling agentsEndpoint: %s', elements))
  }

agentsEndpoint
不返回任何内容。您应该从
promise.all()
返回承诺,然后重写调用
agentsEndpoint
的方式,因为它将返回承诺(即使用
async
/
wait
或常规
。然后对其返回的承诺使用
)-例如,
异步函数listEndpoints(zk){console.log('Calling agentsEndpoint:%s',wait zk.agentsEndpoint());}
Promise.all没有阻塞这一事实是显而易见的,因为承诺本质上是异步的,因此不会阻塞block@JaromandaX我按照你的建议重新编写了代码,它工作了!Thx。但是我可以“隔离”调用方吗(main.js)从这个async/await?我希望我的函数也能简单地返回一个端点数组。再次使用Thx!异步不能被隔离rapping
Promise。Promise中的所有
都是反模式。
Promise。所有
都已返回一个承诺。是的,谢谢。我没有为主题启动程序编写代码的目标。这只是复制粘贴。我尝试了你的解决方案例如,它在语法上看起来是正确的,但a得到了以下错误:const agentsEndpoint=(agentList)=>Promise.all(agentList.map(getData));^TypeError:无法读取的属性“map”undefined@SteveS.该函数希望您传入
agentList
抱歉,我在调用中忽略了这一点。编辑为fix.Humm,现在它偶然发现agentList:zk.agentsEndpoint(agentList)。然后(elements=>console.log('Calling agentsEndpoint:%s',元素))ReferenceError:agentList未定义。agentList在zookeeper.js中定义,而不是在main中。js您在代码中使用的是
agentList
,但在您发布的示例中没有定义。我假设代码中的某个地方有对它的引用。
zk.agentsEndpoint
需要该引用。啊,您可以更改函数不接受该参数。请参见编辑。