Несколько функций, возвращающих обещания - PullRequest
0 голосов
/ 02 ноября 2018

У меня есть помощник 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, которая возвращает обещание с каждым запросом. Пара этих запросов зависит друг от друга. И весь процесс должен вернуть обещание, чтобы все было асинхронно.

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

Это анти-паттерн, верно? Это неправильно.

1 Ответ

0 голосов
/ 02 ноября 2018

Вам действительно не нужно создавать обещание с помощью new, когда вы уже получаете обещание от службы, которую используете. В этом случае просто используйте это обещание и цепочку на нем и, наконец, верните связанное обещание.

Когда вы не используете new Promise, вы явно не звоните reject. Вместо throw в then callback (s). Кроме того, вложенные вызовы 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.";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...