我在node.js应用程序上添加了用户验证和数据修改页面。
在同步宇宙中,在单个函数中我会:
在不起作用的异步Universe中。为了解决这个问题,我建立了一系列切换功能:
router.post('/writeRecord', jsonParser, function(req, res) {
post = req.post;
var smdb = new AWS.DynamoDB.DocumentClient();
var params = { ... }
smdb.query(params, function(err,data){
if( err == null ) writeRecordStep2(post,data);
}
});
function writeRecord2( ru, post, data ){
var conn = new LDAP();
conn.search(
'ou=groups,o=amazon.com',
{ ... },
function(err,resp){
if( err == null ){
writeRecordStep3( ru, post, data, ldap1 )
}
}
}
function writeRecord3( ru, post, data ){
var conn = new LDAP();
conn.search(
'ou=groups,o=amazon.com',
{ ... },
function(err,resp){
if( err == null ){
writeRecordStep4( ru, post, data, ldap1, ldap2 )
}
}
}
function writeRecordStep4( ru, post, data, ldap1, ldap2 ){
// Do stuff with collected data
}
此外,由于LDAP和Dynamo逻辑位于他们自己的源文档中,因此这些函数会在代码周围散布。
这让我觉得效率低下,也不优雅。我渴望找到更自然的异步模式来实现相同的结果。
答案 0 :(得分:0)
如果您还没有听说过蓝鸟,那就试试吧。它转换模块的所有功能并返回当时能够承诺的功能。简而言之,它承诺所有功能。 这是机制:
Module1.someFunction() \\do your job and finally pass the return object to next call
.then() \\Use that object which is return from the first call, do your job and return the updated value
.then() \\same goes on
.catch() \\do your job when any error occurs.
希望你理解。这是一个例子:
var readFile = Promise.promisify(require("fs").readFile);
readFile("myfile.js",
"utf8").then(function(contents) {
return eval(contents);
}).then(function(result) {
console.log("The result of evaluating
myfile.js", result);
}).catch(SyntaxError, function(e) {
console.log("File had syntax error", e);
//Catch any other error
}).catch(function(e) {
console.log("Error reading file", e);
});
答案 1 :(得分:0)
任何承诺库都应该排除您的问题。我最喜欢的选择是蓝鸟。总之,它们可以帮助您执行阻止操作。
答案 2 :(得分:0)
我无法从您的伪代码中确切地知道哪些异步操作依赖于其他操作的结果,并且知道这对于编写一系列异步操作的最有效方式至关重要。如果两个操作不相互依赖,则它们可以并行运行,这通常可以更快地达到最终结果。我也无法确切地告诉我需要将哪些数据传递给异步请求的后续部分(过多的伪代码和足够的真实代码来向我们展示您真正想要做的事情)。 / p>
所以,如果没有那么详细的细节,我会告诉你两种方法来解决这个问题。第一个按顺序运行每个操作。运行第一个异步操作,完成后,运行下一个并将所有结果累积到一个传递给链中下一个链接的对象中。这是通用的,因为所有异步操作都可以访问所有先前的结果。
这使用了AWS.DynamboDB
接口中内置的promise并为conn.search()
做出了自己的承诺(尽管如果我对该接口有更多了解,它可能已经有了一个promise接口)。
这是顺序版本:
// promisify the search method
const util = require('util');
LDAP.prototype.searchAsync = util.promisify(LDAP.prototype.search);
// utility function that does a search and adds the result to the object passed in
// returns a promise that resolves to the object
function ldapSearch(data, key) {
var conn = new LDAP();
return conn.searchAsync('ou=groups,o=amazon.com', { ... }).then(results => {
// put our results onto the passed in object
data[key] = results;
// resolve with the original object (so we can collect data here in a promise chain)
return data;
});
}
router.post('/writeRecord', jsonParser, function(req, res) {
let post = req.post;
let smdb = new AWS.DynamoDB.DocumentClient();
let params = { ... }
// The latest AWS interface gets a promise with the .promise() method
smdb.query(params).promise().then(dbresult => {
return ldapSearch({post, dbresult}, "ldap1");
}).then(result => {
// result.dbresult
// result.ldap1
return ldapSearch(result, "ldap2")
}).then(result => {
// result.dbresult
// result.ldap1
// result.ldap2
// doSomething with all the collected data here
}).catch(err => {
console.log(err);
res.status(500).send("Internal Error");
});
});
而且,这是一个并行版本,它同时运行所有三个异步操作,然后等待所有三个完成,然后立即获得所有结果:
// if the three async operations you show can be done in parallel
// first promisify things
const util = require('util');
LDAP.prototype.searchAsync = util.promisify(LDAP.prototype.search);
function ldapSearch(params) {
var conn = new LDAP();
return conn.searchAsync('ou=groups,o=amazon.com', { ... });
}
router.post('/writeRecord', jsonParser, function(req, res) {
let post = req.post;
let smdb = new AWS.DynamoDB.DocumentClient();
let params = { ... }
Promise.all([
ldapSearch(...),
ldapSearch(...),
smdb.query(params).promise()
]).then(([ldap1Result, ldap2Result, queryResult]) => {
// process ldap1Result, ldap2Result and queryResult here
}).catch(err => {
console.log(err);
res.status(500).send("Internal Error");
});
});
请注意,由于问题中代码的伪代码性质,这也是伪代码,其中包含实施细节(确切地说,您要搜索的参数,以及您发送的响应)等等......)必须填写。这应该说明了对序列化操作进行链接的承诺以及使用Promise.all()
来并行化操作并宣传一种没有内置承诺的方法。< / p>