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

标签 javascript ecmascript-6

我对 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) {
    ...
});

这是旧的 callback style way of handling asynchronous code

您想要编写代码的真正方式是,不是让 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 展开/休息和粗箭头语法。

关于javascript - 在异步函数中返回 promise - 什么是更优雅/更好的实践解决方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54320565/

相关文章:

javascript - 在数组与对象中传播未定义

javascript - 如何在 native react 中单击平面列表项时将值传递给模态并显示模态

javascript - 让 async/await 与 superagent 一起工作

javascript - JavaScript 中嵌套命名空间的继承

javascript - Cufon 无法使用日语文本

javascript - 元标记和 JavaScript 浏览器重定向 - 哪个优先?

javascript - 电子邮件验证正则表达式错误

javascript - 通过字符串引用嵌套的 json 对象属性

javascript - 如何在 Firefox 和 Chrome 中使用 'let'(以及支持的 ECMAScript 6 功能)

javascript - 将项目添加到专用组件中具有数组值的属性