多功能返回承诺

时间:2018-11-02 14:06:45

标签: javascript promise

我有一个HTTP帮助程序,它为每个请求返回一个承诺。有时,这些请求相互依赖。我正在迷惑自己编写我认为是反模式的代码。

通常在链接承诺您使用.then()

function giveMeASimplePromise(){
     return new Promise( function(resolve, reject){
          setTimeout( function(){
               console.log("I'm finishing a promise.");
               resolve();
          }, 3000 );
     });
}

giveMeASimplePromise().then( giveMeASimplePromise ).then( giveMeASimplePromise );

//prints 'I'm finishing a promise' 3 times spaced 3 seconds apart

但是,如果有一个许诺其中一个许诺需要成为链条的一部分,我会感到困惑。

这对我来说很快,因为我有一个HTTP帮助程序函数,该函数会在每个请求中返回一个Promise。这些请求中有几个相互依赖。而且整个过程都需要返回保证所有内容保持异步的承诺。

function login( credentials ){
    //outer promise that's returned and either needs to resolve or reject based
    // on complete login cycle
    return new Promise( function(resolve, reject){
        //inner promise checking for username/password match. can be rejected 
        // for several reasons.
        var checkCredentials = httpHelper.checkCredentials( credentials );
        checkCredentials.then( function(result){
            if ( result.credentialsMatch ){
                //another inner promise checking for privilege levels. never rejects.
                var checkPrivileges = httpHelper.getPrivileges( result.userID ); 
                getPrivileges.then( function(result) ){
                    if( result.privilege > 0 ){
                        //want this to resolve the entire chain
                        resolve();
                    }else{
                        //want this to reject the entire chain
                        reject('You do not have sufficient privileges.');
                    }
                }
            }else{
                reject('Incorrect username and/or password.');
            }
        }).catch( function(reason){
            reject( reason );
        });
    });
}

var credentials = { ... };
var loginResult = login( credentials ).then( function(value){
    console.log('Logged in successfully.');
}).catch( function(reason){
    console.log('Could not log in: ', reason);
})

那是反模式,对吗?感觉不对。

2 个答案:

答案 0 :(得分:2)

当您已经从所使用的服务中获得了承诺时,您确实不需要用new创建承诺。在那种情况下,只需使用 that promise并在其上链接,最后返回链接的promise。

当不使用new Promise时,您显然不会呼叫reject。而是在throw回调中使用then。同样,嵌套的then调用最好上移一层,这样您可以获得平坦的then链。

这是看起来如何:

function login(credentials) {
    return httpHelper.checkCredentials(credentials).then(function(result) {
        if (!result.credentialsMatch) throw "Wrong credentials!";
        return httpHelper.getPrivileges(result.userID); // Don't chain here, but return!
    }).then(function(result) {
        if (result.privilege <= 0) throw "You do not have sufficient privileges.";
    });
}

您可能知道,使用async/await语法时,事情看起来更加简单:

async function login(credentials) {
    const result = await httpHelper.checkCredentials(credentials);
    if (!result.credentialsMatch) throw "Wrong credentials!";
    const result2 = await httpHelper.getPrivileges(result.userID);
    if (result2.privilege <= 0) throw "You do not have sufficient privileges.";
}

答案 1 :(得分:0)

只是想一个假设案例,它可能对登陆此线程的任何人有用。假设 getPrivileges() Promise 没有将 resolve() 解析为可以在第二个 .then() 中验证的值,而是返回一个带有错误消息的 reject() ,我们可以链接一个 catch()并检查错误消息以确定下一步操作。