KKJSBridge
KKJSBridge copied to clipboard
ajax async:false同步请求
ajax async:false同步请求不生效,不会等success回调后再执行下面代码,
我尝试修复,使用window.prompt("SyncCall",obj),但是发现iOS14不行,iOS14以下正常了。
请问有什么好的方案解决同步问题吗?
嗯,你用的是 pod 'KKJSBridge/AjaxHook' 是这个版本吗? 这个版本是统一都当做异步来处理的。
我觉得你还是通过 await 来解决吧。
同求同步解决方案。调试了很久才发现不支持async:false。前端有很多地方使用了async:false,不能要求他们都改成await。🤦♀️
同求同步解决方案。调试了很久才发现不支持async:false。前端有很多地方使用了async:false,不能要求他们都改成await。🤦♀️
你用的是哪种 ajax hook 方案?
# 分别提供了 ajax hook 和 ajax urlprotocol hook 两种方案,可以根据具体需求自由选择。
# 只能选择其中一个方案,默认是 ajax protocol hook。
pod 'KKJSBridge/AjaxProtocolHook'
pod 'KKJSBridge/AjaxHook'
pod 'KKJSBridge/AjaxProtocolHook', '1.3.2' pod 'KKJSBridge/AjaxHook', '1.3.2'
ajax hook 和 ajax urlprotocol hook 方案都支持如下特性:
2020.11.21 (1.3.2)
- 支持 JSBridge 同步调用
- 支持纯文本的 ajax 同步请求(还不支持 Blob 和 表单)
- 支持通过 document.cookie 同步从 NSHTTPCookieStorage 读取最新的 Cookie
已经支持 ajax 同步调用了,目前只支持纯文本的同步调用,还不支持表单的同步调用,不过一般情况下也够用了。
@wjiuxing
Sorry,这几天在老家,只能用手机粗略的看一下。
先把我的经验分享给大家。
以window.prompt 方法同步实属无奈之举,有几点需要注意:
-
prompt 回调方法的 completionHandler,必须且仅需调用一次,不调或者多调都会 crash;
-
completionHandler 要尽早调用,如果是仅需在native侧就能完成的 JS- Native交互,小心一点那还能处理;
-
如果同步Ajax用此方式,native代发同步网络请求是不现实的,发异步请求又会遇见进程间通信超时(会有一条log, [IPC] Connection::waitForSyncReply: Timed-out while waitting for reply...),大概10秒钟左右是冻屏状态。
我在我的fork里做了同步交互的支持(对于没有返回值的同步交互,也尽早消费了 completionHandler,详见 commit https://github.com/wjiuxing/KKJSBridge/commit/d867a85464765da1582a2dd7c4a5b6d8349c8f0e )但是同步 Ajax 还是让 H5 部门修改的。
另外,@KarosLi 我在手机浏览代码时有几个小小的想法:
-
如果必须有的功能,是不是可以考虑放主类里,分类和 associated object 都会影响性能;
-
commit 尽量保持原子性,不提交和本次无关的代码,也可能是我手机看的粗略而没有理解到位 🙏
最后,感谢 @KarosLi 做出的贡献,为我们提供这样一个得心应手的工具,也感谢 @KarosLi 费心竭力为我们解决问题。Thx 🙏
发自Jiuxing Wang's iPhone
在 2020年11月21日,上午12:21,Karosli [email protected] 写道:
@wjiuxinghttps://github.com/wjiuxing
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/karosLi/KKJSBridge/issues/43#issuecomment-731265554, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AA73W2B6YWEZZL6OX3WB3XDSQ2JRHANCNFSM4TEQLL6A.
嗯,感谢你的认真和建议。 这里是出于大家对 ajax sync 同步请求的诉求,所以提供了一个同步方式。不过总体上而言,能让 H5 改的,就尽量让 H5 改,尽量使用 await 或者 使用 ajax async。
1、prompt 回调方法的 completionHandler,目前处理也是只回调一次的。
2、completionHandler 目前的处理要尽早调用,对于没有返回值的同步交互,也尽早消费了 completionHandler。
3、如果同步Ajax用此方式,native代发同步网络请求是不现实的,发异步请求又会遇见进程间通信超时(会有一条log, [IPC] Connection::waitForSyncReply: Timed-out while waitting for reply...),大概10秒钟左右是冻屏状态。 你说的这个情况我相信应该是有的,不过目前我还没测试的那么充分。不过总体上而言,能让 H5 改的,就尽量让 H5 改。
4、之所以放到分类,是考虑到别人不一定会使用 KKWebView,而是自定义的 WKWebView,那分类的话自定义 WKWebView 可以方便集成 JSBridge 同步调用的能力。
5、commit 确实应该要原子提交,这点做得不太好。哈哈,我是有时候考虑的太多,就会把所有地方都改了,有点强迫症。下次你用电脑看吧,然后有问题我们在互相交流。
另外关于 associated,底层实际上还是一个 hash map,对象指针作为 key,时间复杂度是 O(1),性能是上还可以的,只是内存会增加一点。
void _object_set_associative_reference(id object, void *key, id value, uintptr_t policy) {
// retain the new value (if any) outside the lock.
ObjcAssociation old_association(0, nil);
id new_value = value ? acquireValue(value, policy) : nil;
{
AssociationsManager manager;
AssociationsHashMap &associations(manager.associations());
disguised_ptr_t disguised_object = DISGUISE(object);
if (new_value) {
// break any existing association.
AssociationsHashMap::iterator i = associations.find(disguised_object);
if (i != associations.end()) {
// secondary table exists
ObjectAssociationMap *refs = i->second;
ObjectAssociationMap::iterator j = refs->find(key);
if (j != refs->end()) {
old_association = j->second;
j->second = ObjcAssociation(policy, new_value);
} else {
(*refs)[key] = ObjcAssociation(policy, new_value);
}
} else {
// create the new association (first time).
ObjectAssociationMap *refs = new ObjectAssociationMap;
associations[disguised_object] = refs;
(*refs)[key] = ObjcAssociation(policy, new_value);
object->setHasAssociatedObjects();
}
} else {
// setting the association to nil breaks the association.
AssociationsHashMap::iterator i = associations.find(disguised_object);
if (i != associations.end()) {
ObjectAssociationMap *refs = i->second;
ObjectAssociationMap::iterator j = refs->find(key);
if (j != refs->end()) {
old_association = j->second;
refs->erase(j);
}
}
}
}
// release the old value (outside of the lock).
if (old_association.hasValue()) ReleaseValue()(old_association);
}
是的,问题在dealloc的时候会有一些影响。
发自Jiuxing Wang's iPhone
在 2020年11月21日,上午10:42,Karosli [email protected] 写道:
另外关于 associated,底层实际上还是一个 hash map,对象指针作为 key,时间复杂度是 O(1),性能是上还可以的,只是内存会增加一点。
void _object_set_associative_reference(id object, void *key, id value, uintptr_t policy) { // retain the new value (if any) outside the lock. ObjcAssociation old_association(0, nil); id new_value = value ? acquireValue(value, policy) : nil; { AssociationsManager manager; AssociationsHashMap &associations(manager.associations()); disguised_ptr_t disguised_object = DISGUISE(object); if (new_value) { // break any existing association. AssociationsHashMap::iterator i = associations.find(disguised_object); if (i != associations.end()) { // secondary table exists ObjectAssociationMap *refs = i->second; ObjectAssociationMap::iterator j = refs->find(key); if (j != refs->end()) { old_association = j->second; j->second = ObjcAssociation(policy, new_value); } else { (*refs)[key] = ObjcAssociation(policy, new_value); } } else { // create the new association (first time). ObjectAssociationMap *refs = new ObjectAssociationMap; associations[disguised_object] = refs; (*refs)[key] = ObjcAssociation(policy, new_value); object->setHasAssociatedObjects(); } } else { // setting the association to nil breaks the association. AssociationsHashMap::iterator i = associations.find(disguised_object); if (i != associations.end()) { ObjectAssociationMap *refs = i->second; ObjectAssociationMap::iterator j = refs->find(key); if (j != refs->end()) { old_association = j->second; refs->erase(j); } } } } // release the old value (outside of the lock). if (old_association.hasValue()) ReleaseValue()(old_association); }
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/karosLi/KKJSBridge/issues/43#issuecomment-731495064, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AA73W2ETSJQ4Q4KK2RZQUW3SQ4SI5ANCNFSM4TEQLL6A.
同求同步解决方案。调试了很久才发现不支持async:false。前端有很多地方使用了async:false,不能要求他们都改成await。🤦♀️
你用的是哪种 ajax hook 方案?
# 分别提供了 ajax hook 和 ajax urlprotocol hook 两种方案,可以根据具体需求自由选择。 # 只能选择其中一个方案,默认是 ajax protocol hook。 pod 'KKJSBridge/AjaxProtocolHook' pod 'KKJSBridge/AjaxHook'
用的 pod 'KKJSBridge/AjaxProtocolHook', jQuery代码如下:
$.ajax({
type: "POST",
async: false,
headers: {
"Content-Type": 'application/x-www-form-urlencoded;charset=utf-8'
},
url: "/home/page",
data: {
from: "home"
},
success: function (data) {
console.log(111);
alert("success: \n" + data);
},
error: function (error) {
console.log("error");
alert("error: \n" + data);
}
});
pod 'KKJSBridge/AjaxProtocolHook', '1.3.4'
@erickyim 试下这个版本
pod 'KKJSBridge/AjaxProtocolHook', '1.3.4'
@erickyim 试下这个版本
已经可以了,非常感谢~