Weex中js服务的理解

js服务

weex中注册js服务,会在当前运行的js环境中注入一个对应service的create方法返回的对象,这个对象有两种返回形式:

  1. 在返回对象的instance上声明一个实例服务;
  2. 直接在返回对象对象上声明一个服务。

如下面代码中的InstanceService和NormalService

service.register(SERVICE_NAME /* same string with native */, {
  /**
    * JSService lifecycle. JSService `create` will before then each instance lifecycle `create`. The return param `instance` is Weex protected param. This object will return to instance global. Other params will in the `services` at instance.
    *
    * @param  {String} id  instance id
    * @param  {Object} env device environment
    * @return {Object}
    */
  create: function(id, env, config) {
    return {
      instance: {
        InstanceService: function(weex) {
          var modal = weex.requireModule('modal')
          return {
            toast: function(title) {
              modal.toast({ message: title })
            }
          }
        }
      },
      NormalService: function(weex) {
        var modal = weex.requireModule('modal')
        return {
          toast: function(title) {
            modal.toast({ message: title })
          }
        }
      }
    }
  },

  /**
    * JSService lifecycle. JSService `refresh` will before then each instance lifecycle `refresh`. If you want to reset variable or something on instance refresh.
    *
    * @param  {String} id  instance id
    * @param  {Object} env device environment
    */
  refresh: function(id, env, config){

  },

  /**
    * JSService lifecycle. JSService `destroy` will before then each instance lifecycle `destroy`. You can deleted variable here. If you doesn't detete variable define in JSService. The variable will always in the js runtime. It's would be memory leak risk.
    *
    * @param  {String} id  instance id
    * @param  {Object} env device environment
    * @return {Object}
    */
  destroy: function(id, env) {

  }
})

源码理解

我们从源码的角度理解service的注册过程,我们可以在runtime的代码中找到创建服务的方法:

function createServices (id, env, config) {
  // Init JavaScript services for this instance.
  const serviceMap = Object.create(null)
  serviceMap.service = Object.create(null)
  services.forEach(({ name, options }) => {
    if (process.env.NODE_ENV === 'development') {
      console.debug(`[JS Runtime] create service ${name}.`)
    }
    const create = options.create
    if (create) {
      try {
        const result = create(id, env, config)
        Object.assign(serviceMap.service, result)
        Object.assign(serviceMap, result.instance)
      }
      catch (e) {
        console.error(`[JS Runtime] Failed to create service ${name}.`)
      }
    }
  })
  delete serviceMap.service.instance
  Object.freeze(serviceMap.service)
  return serviceMap
}

我们看到在第3行和第4行分别创建了一个serviceMap对象和一个serviceMap上的service对象,这是用来将来保存我们通过两种方式创建的服务的;
接下来我们看第10行,如果注册的服务有create方法,那么我们取它的返回值为result,接下来分别把result上的属性复制到serviceMap.service,把result.instance上的属性复制到serviceMap上,最后返回这个serviceMap。
那么这个serviceMap是怎么放到全局的呢,我们继续查找源码,可以跟踪到createInstanceContext方法,

function createInstanceContext (id, options = {}, data) {
  const weex = new WeexInstance(id, options, data)

  const bundleType = options.bundleType || 'Vue'
  instanceTypeMap[id] = bundleType
  const framework = runtimeConfig.frameworks[bundleType]
  if (!framework) {
    return new Error(`[JS Framework] Invalid bundle type "${bundleType}".`)
  }

  // prepare js service
  const services = createServices(id, {
    weex,
    config: options,
    created: Date.now(),
    framework: bundleType,
    bundleType
  }, runtimeConfig)
  Object.freeze(services)

  // prepare runtime context
  const runtimeContext = Object.create(null)
  Object.assign(runtimeContext, services, {
    weex,
    getJSFMVersion,
    requireModule: (...args) => weex.requireModule(...args),
    __WEEX_CALL_JAVASCRIPT__: receiveTasks,
    services // Temporary compatible with some legacy APIs in Rax
  })
  Object.freeze(runtimeContext)

  // prepare instance context
  const instanceContext = Object.assign({}, runtimeContext)
  if (typeof framework.createInstanceContext === 'function') {
    Object.assign(instanceContext, framework.createInstanceContext(id, runtimeContext, data))
  }
  Object.freeze(instanceContext)
  return instanceContext
}

这个方法是weex的runtime用来创建一个实例的上下文运行环境的,我们看到代码的第12行,调用了createServices来创建services对象,而这个services就是我们上面说的serviceMap对象了。
接下来我们看到在第21行创建了一个空的对象作为运行时的上下文环境,紧接着在22行,把services等对象上的属性复制到这个上下文对象上了,而上下文环境上的属性我们可以当做全局变量来使用。
不好理解的话我们可以结合上面注册的服务的例子,想象一下createInstanceContext最后返回这样一个对象:

{
  service:{
    NormalService:function(weex){
      //...
    }
  },
  InstanceService:function(weex){
    //...
  }
  weex:weex,
  getJSFMVersion:getJSFMVersion,
  __WEEX_CALL_JAVASCRIPT__  
}

这个对象上的属性会被weex的底层注入到全局上下文运行环境中,即这个对象上的属性是全局变量。

使用

因此我们就知道service如何在weex中使用了

<script>
var _InstanceService = new InstanceService(weex)
var _NormalService = new service.NormalService(weex)

module.exports = {
  created: fucntion() {
    // called modal module to toast something
    _InstanceService.toast('Instance JSService')
    _NormalService.toast('Normal JSService')
  }
}
</script>


serviceMap是在instance的create之前服务的create获取的,因此,要想使用service,需要在实例创建之前调用原生平台的代码执行js服务的注册代码完成服务的注册。
Android和IOS原生平台的注册代码这里不再赘述,参见下面的官方文档即可。
参考文档:js服务官方文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一拳小和尚LXY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值