GithubHelp home page GithubHelp logo

codeanalysis's People

Contributors

jyzwf avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar

codeanalysis's Issues

redux 中间件及小点

关于中间件流程,直接看下面一幅图就大致可以理解了
middle2

接下来是一些思考或者说是值得学习的地方

1. createStore.js里面的一个函数 --> ensureCanMutateNextListeners

function ensureCanMutateNextListeners() {
        // 判断 nextListeners 和 currentListeners 是同一个引用
        if (nextListeners === currentListeners) {
            // 通过数组的 slice 方法,复制出一个 listeners ,赋值给 nextListeners
            nextListeners = currentListeners.slice()
        }
    }

为什么要出现这个函数呢??

这部分代码上面有几行英文注释大致讲述了原因,
当我们 dispatch的时候,这时会先执行如下步骤:

        const listeners = (currentListeners = nextListeners)

就是先将 nextListener 赋值给 currentListener 在赋值给 listener ,接着就是执行之前 subscribe 里面注册的监听器了,我们可以想象如下场景:

let unSubscribe1 = store.subscribe(() => {
    let unSubscribe2 = store.subscribe(()=>{})
    // 或者取消之前的一个订阅
})

在执行监听器的时候,里面又进行了订阅,那么,现在假设已经执行了前面订阅的监听函数,现在又取消了,或者又添加了新的订阅监听器,这样子就会出现不确定性和不知名的错误。所以,redux 统一将后面当前 listener 函数执行里面又订阅的 listener 安排到 下一轮 执行。

我们可以分析,当 listener 函数里面又进行 subscribe 时,会调用 ensureCanMutateNextListeners,这时候,currentListeners = nextListeners,会执行 ifnextListeners 将拷贝 currentListeners 的副本,subscribe 订阅的 listener 函数就会被放进 nextListeners,以便下一轮的执行,这样就不会影响到 currentListeners ,也就是本轮执行的 listeners 集合。避免了错误

seajs 阅读感悟

此文是自己对于阅读 Seajs 后的感悟,水平有限,如有不对或者不当,欢迎纠正 ^_^

前言

CMD 对于前端来说耳熟能详,而它是 SeaJS 在推广过程中对模块定义的规范化产出,此前一直对模块化比较新奇和疑惑,但没有细细研究,现在借 SeaJS 来解开自己心中的疑惑,虽说现在 webpack 等工具的兴起使 Seajs 走向了没落,但学习里面的**还是很不错的

当然,本文并不会逐行分析,只是挑重点的来,重点就是 module.js 这个文件

进入正题

我们以以下代码为开端

// 加载一个模块,在加载完成时,执行回调
seajs.use('./A', function(a) {
  a.doSomething();
});


// A.js
define(function(require, exports, module) {
      // 获取模块 B 的接口
      var B = require('./B');

     // 调用模块 B 的方法
     B.doSomething();

      //获取模块 C 的接口
      var C = require('./C');

     // 调用模块 C 的方法
     C.doSomething();

    module.exports = {
       name: 'A',
       doSomething: function() {};
    };
});

// B.js
define(function(require, exports, module) {
      // 获取模块 E 的接口
      var E = require('./E');

     // 调用模块 E 的方法
     E.doSomething();

      //获取模块 F 的接口
      var F = require('./F');

     // 调用模块 F 的方法
     F.doSomething();

    module.exports = {
        name: 'B',
        doSomething: function() {};
    };

});

// E.js、F.js 、C.js 没有依赖,直接暴露接口
define(function(require, exports, module) {
  // 对外提供接口
  module.exports = {
    name: 'x',
    doSomething: function() {};
  };
});

依赖关系如下:
image

M 先会执行 load 方法去加载自己的依赖模块 A ,此时会把自己传给 A 的_entry数组(在pass方法里 ),并将自己的 _entry数组清空,便于下面代码的判断

// If module has entries not be passed, call onload
    // pass方法执行完成后,mod._entry存储被依赖的模块;当前模块加载完成时,执行被依赖模块的回调函数
    // 执行时机为,当依赖模块加载完成后,onload事件发生时,调用该依赖模块的load方法,执行被依赖模块的回调
    if (mod._entry.length) {
        mod.onload()
        return
    }

然后此时 if 不成立,执行后面通过添加 script 标签来加载 A 模块 , A 模块加载的同时,会执行A模块里面的 define 函数,实例化该模块 (调用 save 函数),收集该模块的一些信息,如该模块依赖的模块,模块名,factory 函数

image

A 模块加载好后调用其 load 方法,继续去加载 B、C 模块,注意,他又会在自己的 pass 方法中把 M 模块传给依赖模块,后面依次重复上述过程。
C、E、F每个模块执行 load 里的 pass 方法后,由于此时他们已经没有可以依赖的模块,他们 的 _entry数组里面是最初的 M 模块,回到 load 方法,上面的 if 语句就会执行,调用 onload 方法

image

也就是说,M 模块会被一直向后传递,直到末尾模块才停止,然后每个末尾模块加载好后会去判断是否所有的末尾模块都加载好了,如果是,就执行 M 模块的回调函数。

image

M 的回调函数会依次执行依赖模块的 exec 方法 ,把返回值按顺序传给回调函数使用。

回看每个模块的 exec 方法
这个方法就是将每个模块的 factory 函数进行执行,并将暴露的值返回出去。

总的来说,可以概括如下:
seajs 一开始就去加载各个模块,并在 define 中提取有用信息备用,然后,模块执行时 ,碰到require(‘xxx’),再去执行这个模块的 exec 方法,暴露结果供使用。

前面只是简单的讲了下 module 这个文件的流程,其中还有少可以学习的地方,还有其他文件,如 util-request.js是创建script 标签来请求文件的,util-path.js是用来分析路径的,util-deps.js是用来分析依赖的,等等,都可以学到很多知识。

至此 seajs 就讲完了,欢迎交流 ^_^

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.