简体   繁体   English

多个函数返回承诺

[英]Multiple functions returning promises

I have an HTTP helper that returns a promise for each request.我有一个 HTTP 帮助程序,它为每个请求返回一个承诺。 Sometimes those requests depend on each other.有时,这些请求相互依赖。 I am confusing myself into coding what I think are anti-patterns for this.我让自己陷入编码我认为是反模式的代码中。

Normally when chaining promises you use .then()通常在链接承诺时使用.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

But I am getting confused if there is a promise within one of those promises that needs to be part of the chain.但是,如果需要成为链一部分的那些承诺之一中存在承诺,我会感到困惑。

This is coming up for me because I have an HTTP helper function that returns a promise with each request.这对我来说是因为我有一个 HTTP 帮助函数,它为每个请求返回一个承诺。 A couple of those requests depend on each other.其中一些请求相互依赖。 And the whole process needs to return a promise to keep everything async.并且整个过程需要返回一个保证所有内容异步的承诺。

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);
})

That's an anti-pattern, right?这是一种反模式,对吧? It feels wrong.感觉不对。

You should indeed not need to create a promise with new when you already get a promise from a service you use.当您已经从您使用的服务中获得承诺时,您确实不需要用new创建承诺。 In that case, just use that promise and chain on it and finally return the chained promise.在这种情况下,只需使用承诺并对其进行链接,最后返回链接的承诺。

When not using new Promise you obviously don't call reject .当不使用new Promise您显然不会调用reject Instead throw within the then callback(s).而是在then回调中throw Also the nested then calls should better be moved one level up so you get a flat then chain.此外,嵌套then调用最好向上移动一级,这样您就可以得到一个扁平的then链。

Here is how that could look:这是它的样子:

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.";
    });
}

As you probably know, things look even simpler when you use async/await syntax:您可能知道,当您使用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.";
}

Just thinking of a hypothetical case which could be useful to anyone landin on this thread.只是想一个假设案例,它可能对任何登陆此线程的人有用。 Say if the getPrivileges() Promise does not resolve() to a value which could be validated in the second .then() , and instead returns a reject() with an error message, we could chain a catch() and check for the error message to determine the next action.假设getPrivileges() Promise 没有将 resolve() 解析为可以在第二个 .then() 中验证的值,而是返回一个带有错误消息的 reject(),我们可以链接一个catch()并检查错误消息以确定下一步操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM