在 for 循环打字稿和休眠死锁中调用异步函数
Posted
技术标签:
【中文标题】在 for 循环打字稿和休眠死锁中调用异步函数【英文标题】:Calling an asynchronous function within a for loop typescript and nhibernate deadlock 【发布时间】:2019-02-07 19:54:29 【问题描述】:我正在使用 typescript 在 for 循环中编写一个 http post 调用。
在后端调试方法时,我注意到他同时处理请求。
例如,假设服务器必须在每个请求中运行 2 个方法 M1()
然后 M2()
。对于 n = 2 的测试用例。服务器对请求 1 执行 M1()
,对请求 2 执行 M1()
,然后对请求 2 执行 M2()
,最后对请求 2 执行 M2()
。
那么在_session.commit()
之后,方法intercept中会抛出一个异常。异常描述为:
NHibernate.StaleObjectStateException: '行已被另一个事务更新或删除(或未保存的值映射不正确):[Server.Model.Identity.ApplicationRole#3]'
代码:
public calculate(index?: number): void
for (var i = 0; i < this.policy.coverages.length; i++)
this.callCalculate(i);
public callCalculate(i: number): void
this.premiumCalculationParams = this.policy.createPremiumCalculationParams();
if (!this.premiums)
this.premiums = new Array(this.policy.coverages.length);
this.offerService.calculatePremiums(this.policy, i).then((result: any) =>
this.premiums[i] = new Array<Premium>();
this.surpremiums = new Array<PremiumResult>();
if (result.data && result.data.premiumTable && result.data.premiumTable.premiumPayment && result.data.premiumTable.premiumPayment.premiums && result.data.premiumTable.premiumPayment.premiums.length > 0)
_.each(result.data.premiumTable.premiumPayment.premiums, (premiumValue: any) =>
let premium: Premium = new Premium();
premium.setPremium(premiumValue);
this.premiums[i].push(premium);
this.policy.getCoverage(i).premiumPayment.premiums = angular.copy(this.premiums[i]);
);
if (result.data && result.data.results && result.data.results.length > 0)
_.each(result.data.results, (premiumValuel: any) =>
let sp = new PremiumResult();
sp.setPremiumResult(premiumValuel);
sp.premiums = new Array<Premium>();
_.each(premiumValuel.premiums, (premiumValue: any) =>
let premium: Premium = new Premium();
premium.setPremium(premiumValue);
sp.premiums.push(premium);
);
this.surpremiums.push(sp);
);
console.log(this.surpremiums);
if (result.data && result.data.premiumTable && result.data.premiumTable.messageList && result.data.premiumTable.messageList.messages && result.data.premiumTable.messageList.messages.length > 0)
_.each(result.data.premiumTable.messageList.messages, (message: any) =>
let messageType: any = MessageType[message.messageLevel.toString()];
this.messages.push(new Message(messageType, "premiums", message.messageContent, this.premiums[i]));
);
, (err: any) =>
this.premiums[i] = null;
this.surpremiums = null;
if (err && err.data && err.data.modelState)
for (var key in err.data.modelState)
var model = err.data.modelState[key];
_.each(model, (state: string) =>
this.$log.debug(OfferControllerPrefix, "Calculation failed: " + state);
);
this.messages.push(new Message(MessageType.SVR_ERROR, "premiumCalculationParams", this.jsTranslations.getTranslation(Constants.DEFAULT_ERROR_NL), this.policy));
);
public calculatePremiums(policy: Policy, selectedCoverageIndex : number): any
var uri = this.uriService.buildURI("Policy/Calculate");
var data =
'policy': policy,
'selectedCoverageIndex': selectedCoverageIndex
;
return this.$http.post<any>(uri, data);
如何解决这个问题?
【问题讨论】:
您正在尝试更新已更新的Policy
。你需要检查你的代码而不是那样做。
M1
和 M2
在哪里? calculatePremiums
里面的 POST 是什么?是M1
还是M2
?
是的,http post调用之后,有很多方法在运行。举例来说,假设后端服务器有两个方法M1()和M2()。
在问题中,有一个函数返回一个承诺。另外两个函数返回void
。如果您打算链接它们,这两个函数需要返回承诺。 Promise 的 .then
方法返回一个新的 Promise,该 Promise 产生返回给它的值。
【参考方案1】:
要链接两个异步操作,请将值返回到它们的.then
方法:
function M1(data)
return $http.post(url1, data);
function M2(data)
return $http.post(url2, data);
像这样链接两个函数:
function M1M2 ()
var promise = M1(data);
var promise2 = promise.then(function(data)
var data2 = fn(data);
var m2Promise = M2(data2);
return m2Promise;
);
return promise2;
因为调用 Promise 的 .then
方法会返回一个新的派生 Promise,所以很容易创建一个 Promise 链。
可以创建任意长度的链,并且由于可以使用另一个 Promise 来解决 Promise(这将进一步推迟其解决方案),因此可以在链中的任何点暂停/延迟解决 Promise。这使得实现强大的 API 成为可能。
有关详细信息,请参阅AngularJS $q Service API Reference - chaining promises。
【讨论】:
以上是关于在 for 循环打字稿和休眠死锁中调用异步函数的主要内容,如果未能解决你的问题,请参考以下文章