我有一个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);
})
那是反模式,对吗?感觉不对。
答案 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()
并检查错误消息以确定下一步操作。