1. 需求
环境:FineUICore 本人JS比后台代码多
实际开发中有一个页面是一个父页面套两个iframe子页面,通过js进行交互;
结构图1:
其中有一个方法,由子页面发起,由父页面提交到后台处理(因为参数来自于不同页面),再返回结果由父页面和子页面分别处理;
交互图2:
交互图3:
其中的一些关键方法如下:
关键方法图4:
关键方法图5:
2. 引出问题
这里,父子页面的Save和SaveDone都是非线性的,断开的,如果 有一部分参数想传到SaveDone中还得靠后台中转或存到其他缓存中,而且这样写不方便阅读。
问题图6:
3. 理想策略
这里就要引出js的await方法,处理异步为同步,可以解决上面的问题,让写起来更符合阅读逻辑;
理想写法图7:
4. 改造
如果想要写成await写法,核心F.doPostBack就要返回Promise对象;
js中新建一个方法F.doPostBackP,后台将通过guid找到前台的Promise;
/**
* 2021年12月7日 更新了一下下
* 返回Promise使前台可以同步
* @param {Object} opts 只接收Obj数据
*/
F.doPostBackP = (opts) => {
const _complete = opts.complete;
const autoLoading = opts.autoLoading;
const guid = GetGuid();
opts.complete = (...coms) => {
if (autoLoading) {
autoLoading.split(",").forEach(id => {
if (F.ui[id] && F.ui[id].hideLoading) {
F.ui[id].hideLoading();//showLoading
}
});
}
_complete && _complete.apply(this, [...coms, guid]);
};
return new Promise(r => {
//将r放到指定id中 参数args由后台赋值
F.doPostBack[guid] = r;
if (!opts.params) {
opts.params = {}
}
//后台body中接收postGUID 参照UIdoPostBack
opts.params.postGUID = guid;
if (autoLoading) {
autoLoading.split(",").forEach(id => {
if (F.ui[id] && F.ui[id].showLoading) {
F.ui[id].showLoading();//hideLoading
}
});
opts.enableAjaxLoading = false;
}
//执行原始回发
F.doPostBack(opts);
});
}
在后台的BaseController中 , 增加执行方法,执行结果
/// <summary>
/// 返回参数 注意接收json格式,不支持字符串 配合 doPostBackP
/// </summary>
/// <param name="json"></param>
public void UIdoPostBack(string json)
{
string postGUID = string.Empty;
var Form = FineUICore.PageContext.Current.Request.Form;
if (Form.ContainsKey("postGUID"))
{
postGUID = Form["postGUID"];
}
var Script = $"F.doPostBack['{postGUID}']({json});";
FineUICore.PageContext.RegisterStartupScript(Script);
}
- 这里后台直接输出'""'格式会报错,所以当前只写了输出对象;
最后将理想写法中F.doPostBack改为F.doPostBackP,后台直接调用UIdoPostBack("{msg:'保存成功'}");即可;