由于顶级功能而嵌套的一堆函数是一个ajax请求。 所以我想在嵌套子函数中返回值而不是promise。
父
let getUserPermissions = function(id) {
let deferred = $q.defer();
let promise = accessRequestService.getPermissions(id);
promise.then(function(data) {
deferred.resolve(data);
}, function(err) {
deferred.reject(err);
})
return deferred.promise;
}
儿童1
$rootScope.userInit = function() {
return getUserPermissions(vzid)
.then(function(data) {
//Some code here
return data;
})
}
儿童2
let checkAuthorize = function(toState) {
return $rootScope.userInit().then(
function(data) {
//some code here
return data;
});
}
等级3
checkAuthorize(toState).then( function(val){
$rootScope.isAuthorized = val;
if ($rootScope.isAuthorized == true) {
$log.info('is Authorized')
} else {
$log.info('is not Authorized');
throw new AuthorizationError()
}
})
在第3级,我们仍然在履行承诺。 child 2
可以返回值而不是promise。
期望@ Level 3
$rootScope.isAuthorized = checkAuthorize(toState);
if ($rootScope.isAuthorized == true) {
$log.info('is Authorized')
} else {
$log.info('is not Authorized');
throw new AuthorizationError()
}
答案 0 :(得分:6)
严峻的事实是:你不能,除非你想要意大利面条代码。
最好的解决方案是使用类似ui-router's resolve的内容,在向用户显示页面之前获取所需的所有权限。然后,您可以在控制器上使用它们而无需任何异步调用。
答案 1 :(得分:3)
您可以使用async/await
构造。并使用Babel支持旧浏览器。
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
async function f1() {
var x = await resolveAfter2Seconds(10);
console.log(x); // 10
console.log('done');
}
f1();
答案 2 :(得分:0)
是的,这类事情是可能的,但它会改变行为。您可能希望保留userInit
,但您还要添加userInitValue
变量并按如下方式对其进行初始化:
let userInitValue = null;
let userInit = function() {
return getUserPermissions()
.then(function(data) {
userInitValue = data;
return data;
})
}
所以现在userInitValue
将从null开始,然后再初始化为相关数据。
function isKnownAuthorized(toDoSomething) {
// If we don't know whether the user is authorized
// because we are still waiting for the server to tell us
// then return false and disallow access for now
if(!userInitValue) return false;
// Otherwise return the truth
// (as of when we got the server response)
return userInitValue.isAuthorized(toDoSomething);
}
再次注意行为的变化。获得即时响应的价格(可能在服务器提供数据之前)是即时响应可能是错误的。所以不要在AngularJs中的一次性表达式中使用它。
答案 3 :(得分:0)
基于你希望在Level 3中实现的目标,我猜这个函数将使用相同的输入多次调用。在这种情况下,如果没有缓存结果,我会做的是调用promise,并缓存结果。这样您就不必沿着承诺链走下去,尽管我只计算所提供代码中的一个承诺。解决了多个处理程序,但只有一个承诺。
答案 4 :(得分:0)
您可以使用nsynjs运行您的代码,就好像它是同步的一样:它将逐步评估代码,如果某个函数返回promise,它将暂停执行,等待promise被解析,并分配将结果解析为data
属性。因此,下面的代码将在第1级暂停,直到承诺被解析为实际值。
var getUserPermissions = function(id) {
return new Promise(function(resolve, reject) {
setTimeout(function(){
resolve({
id: id,
isAdmin: "yes he is",
})
}, 1000);
});
};
function synchronousCode() {
console.log("start");
var vzid = 35;
var userInit = function() {
return getUserPermissions(vzid).data;
};
var checkAuthorize = function() {
return userInit().isAdmin;
};
var isAuthorized = checkAuthorize();
console.log(isAuthorized);
};
nsynjs.run(synchronousCode, null, function(){
console.log("finish");
});
<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>
答案 5 :(得分:0)
我正在使用$ state.transitionTo方法在$stateChangeStart
之前调用。
var transitionTo = $state.transitionTo;
$state.transitionTo = function(to, toParams, options) {
var from = $state.$current,
fromParams = $state.params;
to = to.name ? to : $state.get(to);
$rootScope.state = {
to: to.self,
toParams: toParams,
from: from.self,
fromParams: fromParams,
options: options
}
if (options.notify && options.notify !== false) {
return $q.reject(new AuthorizationError('Rejecting $state.transitionTo', 'Transition Rejected'));
} else {
return checkAuthorize(to).then(function(auth) {
$rootScope.isAuthorized = auth;
return transitionTo(to, toParams, options)
})
}
}
<强> StateChangeStart 强>
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
$log.info("Route change start from", fromState.url, "to", toState.url);
//event.preventDefault();
if ($rootScope.isAuthorized == true) {
$log.info('is Authorized')
//$state.go($rootScope.toState.name);
} else {
event.preventDefault();
$log.info('is not Authorized');
throw new AuthorizationError('User is not Authorized.', 'NOT_AUTHENTICATED')
}
});