Javascript Promise.all in Node.js不使用映射和异步调用阻塞函数调用
我编写了一个小模块与Zookeeper对话,以获取服务端点列表。 除了返回端点列表的部分之外,其他部分都可以正常工作。在模块中,我公开了一个函数,该函数应该返回一个端点数组,通过调用getData(从模块节点zookeeper客户端)获得的端点数组的次数与zookeeper上特定路径中的子节点的次数相同。我尝试将数组映射和Promise.all组合起来调用getData x次,但我的函数在Promise.all之前返回,并在调用方以“undefined”变量结尾。下面是我的代码片段: zookeeper.jsJavascript 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
...
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!异步不能被隔离rappingPromise。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
需要该引用。啊,您可以更改函数不接受该参数。请参见编辑。