xd-tayde / blog

博客
850 stars 132 forks source link

关于Native向H5发送数据的一点疑问 #2

Closed WhiteYin closed 6 years ago

WhiteYin commented 6 years ago

《Hybrid App技术解析 -- 实战篇》里说:

Native 完成功能后,直接调用 Bridge.postMessage(handler, data),将 执行结果 和 之前 nativeCall 传过来的 标识 回传给 H5;

postMessage函数的关键代码是:

// 这里将data和handler分别从e变量中抽离出来了
const { handler, data} = e;
...
// 仅传入data
fireEvent(evName,data)

第二步是H5创建并触发名为evName的事件,也就是fireEvent

// 核心代码
function fireEvent(evName,data){
    ...
    if(data && eventItem){
        // 这里挂载在eventItem.data上的只有data,而没有handler
        eventItem.data = data
    }
    ...
    if(eventItem){
        win.dispatchEvent(eventItem)
    }
}

最后,我的理解是触发了“(二) H5 --> Native”这一节讲的nativeCall函数中使用的addEvent()方法:

function nativeCall(...){
    ...
    addEvent(handlerKey.e, e => {
        // 这里的handler是???
        const { data, handler } = e.data
        ...
    })
}

简化下中间过程,就发现Native发送的数据/事件与 H5得到的数据/句柄的关系就是:

{ dataH5,handlerH5 } === dataNative
{ dataNative,handlerNative } === eventNative
// 如果下面这个我所理解的相等关系成立的话,那么是否存在`handler`数据冗余的情况?
handlerH5 === handlerNative 
xd-tayde commented 6 years ago

是的。~你理解得没错。。 handlerH5 === handlerNative。不过这不是冗余。因为就是靠这个协议的唯一标识来进行参数与回调的映射的。~如果没有这样的来回传递,就会出现如果并行两个协议且回调时机不定,则可能就会出现匹配错误。所以。这样的传递是必须的,也是解耦的。

WhiteYin commented 6 years ago

@xd-tayde

如果没有这样的来回传递,就会出现如果并行两个协议且回调时机不定,则可能就会出现匹配错误。

感觉这个只是解释了为什么需要handler这个变量吧。
我理解的handler的作用就是:H5和Native建立一次通信时的唯一标识。

  1. H5生成这个标识在发送请求时带上它;
  2. Native接收到以后保存下来,在返回数据时带上它;
  3. H5在接收数据时根据handler处理指定的回调。 这3个步骤保证了,H5在第三步中接收到的数据,就是自己第一步发出的那个请求需要的数据。也就是解决了所谓的没有标识的异步协议会匹配错误问题?

但我并不是想讨论这个问题……

(1) { dataH5,handlerH5 } === dataNative
(2) { dataNative,handlerNative } === eventNative

由(1)和(2)得:

(3) { { dataH5,handlerH5 } , handlerNative } === eventNative

(4) handlerH5 === handlerNative

那不就说明,Native在调用postMessage时 ,传入的e,它有一个handler属性,而它的data属性值中也有一个handler属性,并且这两个属性值是一个值……


如果是刻意这么设计的,那是为了解决什么痛点…… 毕竟我感觉把postMessage设计成下面这样:

function postMessage(e){
    const {handler,data} = e
    // 加个对象,因为不知道e是不是有别的属性
   const newDate = {
       handler,
       data
   }
    ...
    fireEvent(evName,newDate)
}

好像也没什么问题呀……


= =我因为没有jsbridge相关经验啊,所以不知道是不是有什么痛点我没有考虑到。只是直觉上觉得有点奇怪。

xd-tayde commented 6 years ago

哦。~理解你说的。~不过这里有个误会。由

(1) { dataH5,handlerH5 } === dataNative

dataH5 与 dataNative 并不存在关联,dataH5是指传递的参数,而dataNative是结果返回,举个例:做代理请求时:

dataH5 : {url : 'http://www.xx.com'} dataNative: {response: [1,2,3,]}

另外,你后面说的 newData, 其中从业务方来说,并不需要关心 handler,而且 fireEvent 中也已经与 handler 解耦,因此并不需要将 handler 的值与 data 挂载在一起。只需要 fireEvent(eN, data); 而此时的 data(dataNative) 中,并不包含 handler。

不知道这样解释能理解吗。?。感谢您的建议~

WhiteYin commented 6 years ago

@xd-tayde 抱歉,是我没有说明dataH5dataNative的定义,导致了这两天鸡同鸭讲的情况。
我把dataH5dataNative什么的代入到全过程,您再看看吧。

// Native返回数据
function postMessage(eventNative){
    // 等式(2)
    const { handlerNative, dataNative} = eventNative;
    ...
    // 触发事件
    fireEvent(evName,dataNative)
}
// Native触发指定事件
function fireEvent(evName,dataNative){
    ...
    if(dataNative && eventItem){
        eventItem.data = dataNative
    }
    ...
    if(eventItem){
        win.dispatchEvent(eventItem)
    }
}
// H5发送请求
function nativeCall(...){
    ...
    // 添加事件监听
    addEvent(handlerKey.e, e => {
        // 等式(1)
        const { dataH5, handlerH5 } = e.data
        ...
    })
}

=。=如果还是没能改变我们俩沟通问题的话,那就算了。很期待后续文章以及图片处理系列,毕竟当初在知乎美图专栏上看了前两篇就不更了……

xd-tayde commented 6 years ago

~感谢哈。确实在数据的传递上之前有点疏忽,已经有做了修改了哈。。哈哈。图片处理的那个系列还有个(四)。。三的话一直没时间写。

WhiteYin commented 6 years ago

@xd-tayde 昂,我有看到(四)的。
我也不是很着急……只是对图片处理这方面感兴趣,因为想在我的个人项目里做一个图片加滤镜之类的功能。