在异步函数中返回承诺-什么是更优雅/实践更好的解决方案



我对async/await还很陌生,虽然下面的代码似乎运行得很好,但我觉得必须有一种更优雅/最佳实践的方法来编写这个函数:

/**
* 
* @param {string} email user email address
* @description validates project exists and project owner is userId.
* @returns {Promise} resolves userId if found otherwise null
*/
async getUserFirstAndLastName (userId) {
var userName;
return new Promise(function(resolve, reject){
var params = {
UserPoolId: process.env.userPoolId, /* required */
AttributesToGet: [
'given_name',
'family_name'
/* more items */
],
Filter: `sub = "${userId}"`
};
console.log("UserUtils DDB Get User First and Last Name:" + JSON.stringify(params, null,'  '));
cognitoidentityserviceprovider.listUsers(params, function(err, data) {
if(err){ // an error occurred
console.log(err, err.stack);
reject(err); // throw error
}
else { // successful response
console.log("Data: " + JSON.stringify(data, null,'  '));
if(data.Users.length){
userName = data.Users[0].Attributes[0].Value + " "; // First Name
userName += data.Users[0].Attributes[1].Value; // Last Name
resolve(userName); //return
}
else {
resolve(null); // no user found that matches email
}
}
});
});
}

寻求指导。。。

代码的问题似乎真的围绕着这一行:

cognitoidentityserviceprovider.listUsers(params, function(err, data) {
...
});

这是处理异步代码的老式回调方式。

编写代码的真正方法是,listUsers函数不接受回调,而是返回promise。然后你可以这样写代码:

async getUserFirstAndLastName (userId) {
const params = {
UserPoolId: process.env.userPoolId, /* required */
AttributesToGet: [
'given_name',
'family_name'
/* more items */
],
Filter: `sub = "${userId}"`
};
try {
const data = await cognitoidentityserviceprovider.listUsers(params);
if(data.Users.length){
let userName = data.Users[0].Attributes[0].Value + " "; // First Name
userName += data.Users[0].Attributes[1].Value; // Last Name
return userName; 
}
else {
return null; // no user found that matches email
}
}catch(err) {
throw err; 
});
});
}

假设您不能直接重写listUsers函数,那么您可以编写一个函数,将其转换为返回promise的函数,如下所示:

function convertCallbackFnToAsyncFn(fn) {
//Note that we are returning a function
return (...args) => new Promise(function(resolve, reject){
fn(...args, (err, data) => {
if (err) {
reject(err); 
}
else {
resolve(data); 
}
}); 
}); 
}

将其与上述解决方案相结合:

try {
//I'm just naming it newFunction here to be really clear about what we're doing
const newFunction = convertCallbackFnToAsyncFn(cognitoidentityserviceprovider.listUsers);
const data = await newFunction(params);
....

请注意,我在回答中使用了一些ES6 spread/rest和胖箭头语法。

最新更新