国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

seajs 模塊源碼解讀

e10101 / 2691人閱讀

摘要:這里的依賴都是通過來異步加載的,加載完畢之后立刻執行函數,在模塊文件執行完畢后包括和其他代碼,觸發的事件。

入口 seajs.use

seajs.use直接調用Module.use(),Module.use的源碼如下:

// Use function is equal to load a anonymous module
// ids:模塊標識,uri是dirname + "_use_0" + 數字自增變量
Module.use = function (ids, callback, uri) {
 // 從緩存cachedMods中獲取已存在的模塊對象或者新建module對象,并將緩存寫入其中,返回當前模塊對象
  var mod = Module.get(uri, isArray(ids) ? ids : [ids])

  // 對使用seajs.use或者require.async的模塊掛在一個callback。seajs.use的callback在所有依賴都loaded完畢之后才執行,通過require遞歸的exec()各個已經loaded的依賴模塊。這個callback作為seajs的入口,是所有模塊的factory開始執行的線頭起點。
  mod.callback = function() {
    var exports = []
    // resolve通過正則表達式解析當前模塊的依賴deps,并返回解析后的完成路徑,其值為一個數組
    var uris = mod.resolve()

    // seajs.use入口處的依賴模塊依次開始執行,此為模塊執行的起點
    for (var i = 0, len = uris.length; i < len; i++) {
      exports[i] = cachedMods[uris[i]].exec()
    }

    if (callback) {
      callback.apply(global, exports)
    }

    delete mod.callback
  }

  mod.load()
}

// Get an existed module or create a new one
Module.get = function(uri, deps) {
  return cachedMods[uri] || (cachedMods[uri] = new Module(uri, deps))
}

// Module構造函數
function Module(uri, deps) {
  this.uri = uri
  this.dependencies = deps || []
  this.exports = null
  this.status = 0

  // Who depends on me
  this._waitings = {}  // 依賴當前模塊的對象

  // The number of unloaded dependencies
  this._remain = 0 // 依賴的未加載完畢的模塊個數
}

load:加載當前模塊的依賴,并且在當前模塊的所有依賴都加載完畢后,觸發onload函數

// Load module.dependencies and fire onload when all done
Module.prototype.load = function() {
  var mod = this

  // If the module is being loaded, just wait it onload call
  // 如果當前模塊正在被加載或者已經加載完畢,直接返回
  if (mod.status >= STATUS.LOADING) {
    return
  }
  // 設置當前模塊為加載狀態
  mod.status = STATUS.LOADING

  // Emit `load` event for plugins such as combo plugin
  // 解析當前加載模塊所有依賴文件的完整路徑
  var uris = mod.resolve()
  emit("load", uris, mod)
  
  // 初始化模塊所依賴的未加載完畢的模塊的個數
  var len = mod._remain = uris.length
  var m

  // Initialize modules and register waitings
  // 依次初始化當前mod依賴的deps為module對象,并且初始化_waitings,并存入cacheMods
  for (var i = 0; i < len; i++) {
    m = Module.get(uris[i])

    if (m.status < STATUS.LOADED) {
      // Maybe duplicate: When module has dupliate dependency, it should be it"s count, not 1
      // 如果當前依賴為未加載完成狀態,則該模塊的waiting + 1
      m._waitings[mod.uri] = (m._waitings[mod.uri] || 0) + 1
    } else {
      // 當前依賴已經加載完成,則模塊的remain - 1
      mod._remain--
    }
  }
  
  // 當前模塊的所有依賴都已經加載完畢時,觸發onload
  if (mod._remain === 0) {
    mod.onload()
    return
  }

  // Begin parallel loading
  var requestCache = {}
  // 通過fetch函數,加載當前mod依賴的所有模塊
  for (i = 0; i < len; i++) {
    m = cachedMods[uris[i]]

    if (m.status < STATUS.FETCHING) {
      m.fetch(requestCache)
    } else if (m.status === STATUS.SAVED) {
      m.load()
    }
  }

  // Send all requests at last to avoid cache bug in IE6-9. Issues#808
  for (var requestUri in requestCache) {
    if (requestCache.hasOwnProperty(requestUri)) {
      requestCache[requestUri]()
    }
  }
}

// Call this method when module is loaded
// 模塊的所有依賴都加載完畢后,執行onload
Module.prototype.onload = function() {
  var mod = this
  mod.status = STATUS.LOADED
  
  // 對于使用require.async定義的模塊,有callback函數,在所有依賴模塊加載完畢后執行callback函數
  if (mod.callback) {
    mod.callback()
  }

  // Notify waiting modules to fire onload
  // 當前模塊的所有依賴都加載完畢后,通知依賴當前模塊的所有模塊
  var waitings = mod._waitings;
  var uri, m;
  for (uri in waitings) {
    if (waitings.hasOwnProperty(uri)) {
      m = cachedMods[uri]
      m._remain -= waitings[uri]
      if (m._remain === 0) {
        // 遞歸調用依賴當前模塊的模塊,執行onload函數,直到module.use頂端
        m.onload()
      }
    }
  }

  // Reduce memory taken
  delete mod._waitings
  delete mod._remain
}

fetch: fetch主要是通過創建標簽并且append到head來實現依賴的加載。這里的依賴都是通過async來異步加載的,加載完畢之后立刻執行define函數,在模塊文件執行完畢后(包括define和其他js代碼),觸發script的onload事件。

// Fetch a module
Module.prototype.fetch = function(requestCache) {
  var mod = this
  var uri = mod.uri

  mod.status = STATUS.FETCHING

  // Emit `fetch` event for plugins such as combo plugin
  var emitData = {
    uri: uri
  }
  emit("fetch", emitData)
  var requestUri = emitData.requestUri || uri

  // Empty uri or a non-CMD module
  if (!requestUri || fetchedList[requestUri]) {
    mod.load()
    return
  }

  // fetchingList和callbackList為兩個全局對象,分別存放正在加載的模塊列表?????
  if (fetchingList[requestUri]) {
    callbackList[requestUri].push(mod)
    return
  }

  fetchingList[requestUri] = true
  callbackList[requestUri] = [mod]

  // Emit `request` event for plugins such as text plugin
  emit("request", emitData = {
    uri: uri,
    requestUri: requestUri,
    onRequest: onRequest,
    charset: data.charset
  })

  if (!emitData.requested) {
    requestCache ? requestCache[emitData.requestUri] = sendRequest : sendRequest()
  }

  function sendRequest() {
    seajs.request(emitData.requestUri, emitData.onRequest, emitData.charset)
  }
  
  // script標簽的onload事件發生后,觸發onRequest方法
  function onRequest() {
    delete fetchingList[requestUri]
    fetchedList[requestUri] = true

    // Save meta data of anonymous module
    if (anonymousMeta) {
      Module.save(uri, anonymousMeta)
      anonymousMeta = null
    }

    // Call callbacks
    var m, mods = callbackList[requestUri]
    delete callbackList[requestUri]
    while ((m = mods.shift()))
      m.load()
  }
}

request: 將script添加到head,并且定義onload事件

seajs.request = function (url, callback, charset) {
    var isCSS = IS_CSS_RE.test(url)
    var node = doc.createElement( isCSS ? "link" : "script")

    if (charset) {
      var cs = isFunction(charset) ? charset(url) : charset
      if (cs) {
        node.charset = cs
      }
    }

    addOnload(node, callback, isCSS, url)

    if (isCSS) {
      node.rel = "stylesheet"
      node.href = url
    } else {
      node.async = true
      node.src = url
    }

    // For some cache cases in IE 6-8, the script executes IMMEDIATELY after
    // the end of the insert execution, so use `currentlyAddingScript` to
    // hold current node, for deriving url in `define` call
    currentlyAddingScript = node

    // ref: #185 & http://dev.jquery.com/ticket/2709
    baseElement ? head.insertBefore(node, baseElement) : head.appendChild(node)

    currentlyAddingScript = null
  }

  function addOnload(node, callback, isCSS, url) {
    var supportOnload = "onload" in node

    // for Old WebKit and Old Firefox
    if (isCSS && (isOldWebKit || !supportOnload)) {
      setTimeout(function() {
        pollCss(node, callback)
      }, 1) // Begin after node insertion
      return
    }

    if (supportOnload) {
      node.onload = onload
      node.onerror = function() {
        emit("error", {
          uri: url,
          node: node
        })
        onload()
      }
    } else {
      node.onreadystatechange = function() {
        if (/loaded|complete/.test(node.readyState)) {
          onload()
        }
      }
    }

    function onload() {
      // Ensure only run once and handle memory leak in IE
      node.onload = node.onerror = node.onreadystatechange = null

      // Remove the script to reduce memory leak
      if (!isCSS && !data.debug) {
        head.removeChild(node)
      }

      // Dereference the node
      node = null

      callback()
    }
  }

Module.define

// Define a module
Module.define = function(id, deps, factory) {
  var argsLen = arguments.length

  // define(factory)
  if (argsLen === 1) {
    factory = id
    id = undefined
  } else if (argsLen === 2) {
    factory = deps

    // define(deps, factory)
    if (isArray(id)) {
      deps = id
      id = undefined1 `1` // define(id, factory)
      ``
    } else {
      deps = undefined
    }
  }

  // Parse dependencies according to the module factory code
  if (!isArray(deps) && isFunction(factory)) {
    deps = parseDependencies(factory.toString())
  }

  var meta = {
    id: id,
    uri: Module.resolve(id),
    deps: deps,
    factory: factory
  }

  // Try to derive uri in IE6-9 for anonymous modules
  if (!meta.uri && doc.attachEvent) {
    var script = getCurrentScript()

    if (script) {
      meta.uri = script.src
    }

    // NOTE: If the id-deriving methods above is failed, then falls back
    // to use onload event to get the uri
  }

  // Emit `define` event, used in nocache plugin, seajs node version etc
  emit("define", meta)
  
  // Save information for "saving" work in the script onload event
  meta.uri ? Module.save(meta.uri, meta) : anonymousMeta = meta
}

resolve

// Resolve module.dependencies
Module.prototype.resolve = function() {
  var mod = this
  var ids = mod.dependencies
  var uris = []

  for (var i = 0, len = ids.length; i < len; i++) {
    uris[i] = Module.resolve(ids[i], mod.uri)
  }
  return uris
}

// Resolve id to uri
Module.resolve = function(id, refUri) {
  // Emit `resolve` event for plugins such as text plugin
  var emitData = { id: id, refUri: refUri }
  emit("resolve", emitData)

  return emitData.uri || seajs.resolve(emitData.id, refUri)
}


function id2Uri(id, refUri) {
  if (!id) return ""

  id = parseAlias(id)
  id = parsePaths(id)
  id = parseVars(id)
  id = normalize(id)

  var uri = addBase(id, refUri)
  uri = parseMap(uri)

  return uri
}

seajs.resolve = id2Uri;
參考文獻

https://seajs.github.io/seajs...
https://github.com/seajs/exam...
https://github.com/seajs/seajs

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99020.html

相關文章

  • seajs 源碼解讀

    摘要:本文主要簡單地解讀一下的源碼和模塊化原理。其中,是這次源碼解讀的核心,但我也會順帶介紹一下其他文件的作用的。對代碼比較簡單,其實就是聲明一下全局的命名空間。然而,真正的核心在于處理模塊依賴的問題。 seajs 簡單介紹 seajs是前端應用模塊化開發的一種很好的解決方案。對于多人協作開發的、復雜龐大的前端項目尤其有用。簡單的介紹不多說,大家可以到seajs的官網seajs.org參看...

    LiangJ 評論0 收藏0
  • Seajs源碼解讀

    摘要:如果這個模塊的時候沒有設置,就表示是個匿名模塊,那怎么才能與之前發起請求的那個相匹配呢這里就有了一個全局變量,先將元數據放入這個對象。模塊加載完畢的回調保存元數據到匿名模塊,為請求的不管是不是匿名模塊,最后都是通過方法,將元數據存入到中。 近幾年前端工程化越來越完善,打包工具也已經是前端標配了,像seajs這種老古董早已停止維護,而且使用的人估計也幾個了。但這并不能阻止好奇的我,為了了...

    bigdevil_s 評論0 收藏0
  • JavaScript模塊化發展

    摘要:所有依賴這個模塊的語句,都定義在一個回調函數中,等到所有依賴加載完成之后前置依賴,這個回調函數才會運行。如果將前面的代碼改寫成形式,就是下面這樣定義了一個文件,該文件依賴模塊,當模塊加載完畢之后執行回調函數,這里并沒有暴露任何變量。 模塊化是我們日常開發都要用到的基本技能,使用簡單且方便,但是很少人能說出來但是的原因及發展過程。現在通過對比不同時期的js的發展,將JavaScript模...

    mengbo 評論0 收藏0
  • seajs源碼解析

    摘要:最后將執行的結果暴露給對象。腳本事件在腳本執行的時候不會立馬觸發解決辦法是通過腳本的來判斷總結以上就是對的一個大致的分析,如有錯誤,歡迎指出。 Seajs是一款模塊化開發框架,遵循CMD規范。雖然到現在為止很多模塊打包工具比它更加的完善,但還是有必要拜讀一下的,畢竟為前端模塊化的發展做了很大的貢獻,分析一下漲漲姿勢。文章主要從以下幾個方面來分析。有不對的地方,歡迎大家指出。 1、什么是...

    YPHP 評論0 收藏0
  • cordova研習筆記(二) —— cordova 6.X 源碼解讀(上)

    摘要:本文源碼為版本。的代碼結構也是一個很經典的定義結構構造函數實例修改函數原型共享實例方法,它提供事件通道上事件的訂閱撤消訂閱調用。 前言 cordova(PhoneGap) 是一個優秀的經典的中間件框架,網上對其源代碼解讀的文章確實不多,本系列文章試著解讀一下,以便對cordova 框架的原理理解得更深入。本文源碼為cordova android版本6.1.2。 源碼結構 我們使用IDE...

    Java_oldboy 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<