记一次基于ABP框架使用ajax请求
最近基于ABP框架做一个简单的认证功能。先来看看需求。
1.需求
点击认证按钮,弹出对应的认证或取消认证提示框。经过确认后,认证状态由“已认证”转为“未认证”。反之亦然。
2.思路
1.通过该行的主键,获取到Status属性的值0/1。函数为GetStatusAsync
。
2.如果为0,进行认证操作;如果为1,进行取消认证操作。函数为ProcessAuthenticateAsync
。
3.前端通过GetStatusAsync
获取Status值,返回值为1,弹窗提示“是否取消认证”;返回值为0,弹窗提示“是否认证”。
4.点击确认后,后台进行处理,进行第二步操作。
3.实现
后台代码:
-
public async Task<int> GetStatusAsync(EntityDto<int> input) { var entity = await _weldProcessRepository.GetAsync(input.Id); int rzid =0; if(entity.Status == 1) { rzid = 1; }else if(entity.Status == 0) { rzid = 0; } return rzid; }
-
public async Task<bool> ProcessAuthenticateAsync(EntityDto<int> input) { var entity = await _weldProcessRepository.GetAsync(input.Id); if(entity.Status == 0) { entity.Status = 1; } else if(entity.Status == 1) { entity.Status = 0; } return true; }
前端代码:
1.原来的JS代码。
通过这种方法获取所选数据的Status属性值。
1.点击事件
'click .processAuthenticate': function (e, value, row, index) {
authenticateWeldProcess(row);
}
//
2. 获取status值
function getstatus(weldProcess) {
return _weldProcessService.GetStatusAsync(weldProcess);
}
3.点击后处理事件。主要是根据获取的status进行弹出的对话框选择。是否认证和取消认证两种。
function authenticateWeldProcess(weldProcess) {
var rzid = getstatus(weldProcess.Id);
if (rzid == "0") { //进行认证
abp.message.confirm( app.localize('WeldProcessAuthenticateWarningMessage', weldProcess.Id),
function (isConfirmed) {
if (isConfirmed) { _weldProcessService.processAuthenticateAsync({
id: weldProcess.Id
}).done(function () { _$table.bootstrapTable('refresh'); abp.notify.success(app.localize("SuccessfullyAuthenticated"));
});
}
}
);
}
else { //取消认证
abp.message.confirm(
app.localize('UnWeldProcessAuthenticateWarningMessage', weldProcess.Id),
function (isConfirmed) {
if (isConfirmed) { _weldProcessService.processAuthenticateAsync({
id: weldProcess.Id
}).done(function () { _$table.bootstrapTable('refresh'); abp.notify.success(app.localize("SuccessfullyUnAuthenticated"));
});
}
}
);
}
}
这样子完成后,通过调试发现 if(rzid == “0”) 永远不成立,点击认证按钮一直都是出现取消认证的提示弹窗(也可能是一直出现认证的弹窗,取决于判断条件),通过单步调试了非常久的时间,发现了使用_weldProcessService.GetStatusAsync(weldProcess.Id)
这种方式调用,其实是使用了ajax请求,而GetStatusAsync
方法也是一个异步执行的函数。ajax请求默认是异步的。
JavaScript 中有同步代码与异步代码。一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
调试过程发现,后台的GetStatusAsync
函数在执行完弹窗后才调用,本来应该是先执行GetStatusAsync
,得到status后才选择弹窗,现在无法获取status。
现在问题很明显了,真是**ajax(异步的 JavaScript 和 XML)**的异步请求造成的。后面重新改写代码。
修改ajax请求为同步执行。这样就可以获取status,阻塞主线程。弹窗就会根据status来选择了。
修改的js代码:
var rzid;
function authenticateWeldProcess(weldProcess) {
rzajax = $.ajax({
url: 'api/services/app/weldProcess/GetStatusAsync',
type: 'POST',
async: false,
data: {"id":weldProcess.Id},
/* dataType:"application/json",*/
success: function (data) {
rzid = data.result;
}
});
$.when(rzajax).done(function () {
if (rzid == "0") { //进行认证
abp.message.confirm(
app.localize('WeldProcessAuthenticateWarningMessage', weldProcess.Id),
function (isConfirmed) {
if (isConfirmed) {
_weldProcessService.processAuthenticateAsync({
id: weldProcess.Id
}).done(function () {
_$table.bootstrapTable('refresh');
abp.notify.success(app.localize("SuccessfullyAuthenticated"));
});
}
}
);
}
else { //取消认证
abp.message.confirm(
app.localize('UnWeldProcessAuthenticateWarningMessage', weldProcess.Id),
function (isConfirmed) {
if (isConfirmed) {
_weldProcessService.processAuthenticateAsync({
id: weldProcess.Id
}).done(function () {
_$table.bootstrapTable('refresh');
abp.notify.success(app.localize("SuccessfullyUnAuthenticated"));
});
}
}
);
}
});
return rzid;
};
最后大功告成。
后来查找资料还发现了同样的解决方式。
总结:
1.单步调试是个好东西。
2.对技术的底层与实现方法也需要了解,方便在出问题的时候从根本解决问题。
3.大胆尝试