承诺地狱、反模式和错误处理

Oza*_*ürk 3 javascript node.js es6-promise

我是 node.js 环境的新手。我阅读了很多有关实现 Promise 并将它们链接在一起的资料。我试图避免反模式实现,但我不知道如何做到这一点。

系统中有一个用户注册流程。首先,我检查用户名。如果数据库中没有使用此用户名的用户,我将创建一个用户模型并将其保存到数据库中。

您能看到我的内联评论吗?

应用程序.js

RegisterUser("existUser","123").then(user=>{
    //send response, etc
}).catch(er => {
    console.log(er);
    //log error,send proper response, etc
    // Should I catch error here or inner scope where RegisterUser implemented ?
});
Run Code Online (Sandbox Code Playgroud)

用户服务.js

function RegisterUser(username, password) {
    return new Promise((resolve, reject) => {
        GetUser(username) 
            .then(user=>{
                if(user)reject(new Error("User Exists"));
                else{
                    resolve(SaveUser(username,password))// Is that ugly?
                                                        //what if I have one more repository logic here ?
                                                        //callback train... 
                }
            }) 
            .then(user => {
                resolve(user);//If I do not want to resolve anything what is the best practice for it, like void functions?
            }).catch(err=>{
                console.log(err); // I catch the db error what will I do now :)
                reject(err);// It seems not good way to handle it, isn't it ?
                // Upper promise will handle that too. But I dont know how can I deal with that.
            });;
    });
}
Run Code Online (Sandbox Code Playgroud)

存储库.js

function GetUser(username) {
    return new Promise((resolve, reject) => {
        if (username === "existUser")
            resolve("existUser");
        else resolve("");
    });
}

function SaveUser(username, password) {
    return new Promise((resolve, reject) => {
        reject(new Error("There is a problem with db"));//assume we forgot to run mongod 
    });
}
Run Code Online (Sandbox Code Playgroud)

上面的代码对我来说似乎很糟糕。我想我需要定义一些可以在 GetUser 方法之后链接的方法。喜欢

GetUser(username)
.then(SaveUserRefined)// how could it know other parameters like password, etc
.then(user=> {resolve(user)}) // resolve inside then ? confusing.
.catch(er=>//...);
Run Code Online (Sandbox Code Playgroud)

我觉得我在这里做了反模式并创建了“承诺地狱”如何实现像这样的简单流程。验证用户名并保存。

谢谢。

Ber*_*rgi 5

是的,这就是Promise构造函数反模式!写吧

function registerUser(username, password) {
    return getUser(username).then(user => {
        if (user) throw new Error("User Exists");
        else return saveUser(username,password)
    });
}
Run Code Online (Sandbox Code Playgroud)

请注意,我还小写了您的函数名称。您应该只将构造函数大写。

我应该在此处捕获错误还是在registerUser实现的内部范围内捕获错误?

您应该在可以处理错误的地方捕获错误 - 并且应该在链的末尾处理错误(通常通过记录它们)。如果registerUser不提供回退结果,则它不需要处理任何内容,并且通常也不需要自行记录错误消息(如果您愿意,请参阅此处的示例)。

另请参阅即使我在所有 then-ables 中使用拒绝回调,我最后是否总是需要 catch() ?