subscription

概述

subscription.js 文件是用来处理 model.subscriptions 的。

源码地址

dva/packages/dva-core/src/subscription.js

解析

subscription.js 文件对外暴露两个方法:run 和 unlisten,接下来我们就来分析下这两个方法。

run

run 方法的作用是执行 subscriptions。

  • subs 就是 model.subscriptions
  • 对 subs 进行遍历,先判断 key 是否是 subs 的自身属性
  • 如果是则依次调用每一个 subscription,参数有两个一个对象包含一个经过 prefixedDispatch 处理过的 dispatch 和 history 对象,另一个是 onError
  • 上述调用的返回值赋值给常量 unlistener,如果其为 function 则存入 funcs 否则存入 nonFuncs
  • 最后返回 { funcs, nonFuncs }
export function run(subs, model, app, onError) {
  const funcs = [];
  const nonFuncs = [];
  for (const key in subs) {
    if (Object.prototype.hasOwnProperty.call(subs, key)) {
      const sub = subs[key];
      const unlistener = sub({
        dispatch: prefixedDispatch(app._store.dispatch, model),
        history: app._history,
      }, onError);
      if (isFunction(unlistener)) {
        funcs.push(unlistener);
      } else {
        nonFuncs.push(key);
      }
    }
  }
  return { funcs, nonFuncs };
}

unlisten

我们知道如果你要使用 app.unmodel 和 app.replaceModel 方法,则 subscription 必须返回 unlisten 方法,用于取消数据订阅。 而 unlisten 方法就是用于调用 unlisten 方法的。

  • unlisten 方法接受一个 unlisteners 和一个 namespace,unlisteners 是一个对象存储了所有 run 方法执行的结果按照 namespace 进行分类
  • 首先判断传入的 namespace 是否在 unlisteners 上有对应的值
  • 如果有值,则对其结构返回 funcs 和 nonFuncs 我们上面说过如果 subscription 执行完返回的结果是一个 function 则存入 funcs,否则存入 nonFuncs
  • 接下来对 nonFuncs 做校验,如果不为空说明没有返回取消订阅的方法
  • 依次调用所有 funcs 里面的方法
  • 最后删除 unlisteners 里面对应的 namespace 值
export function unlisten(unlisteners, namespace) {
  if (!unlisteners[namespace]) return;

  const { funcs, nonFuncs } = unlisteners[namespace];
  warning(
    nonFuncs.length === 0,
    `[app.unmodel] subscription should return unlistener function, check these subscriptions ${nonFuncs.join(', ')}`,
  );
  for (const unlistener of funcs) {
    unlistener();
  }
  delete unlisteners[namespace];
}