我有一个HTTP助手,它为每个请求返回一个promise。有时这些请求相互依赖。我很困惑自己编写我认为反模式的代码。
通常在链接承诺时使用.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);
})
这是一种反模式,对吧?感觉不对。
当您已经从您使用的服务获得承诺时,您确实不需要使用new
创建承诺。在这种情况下,只需在其上使用该承诺和链,最后返回链式承诺。
当不使用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.";
}