2016-01-13 71 views
2

正向我自己的滾動需要

它已經到了我的注意,這個問題是一個「函數的範圍, - 不阻塞作用域」的答案,不同之處for ... in反對for ... i<n ... i++該解決方案可以包裹for(var p in ...) {與一個給他們自己的範圍的功能(很像Array.prototype.forEach)。感謝您的幫助。

問題

我滾我自己的小Require.js的解決方案,而不是實際的Require.js庫(不,我還沒有采取一起來看看它們的源)。

我的回調函數似乎從未被執行,但我不明白爲什麼。這可能是一個簡單的邏輯錯誤,但是當你長時間盯着你自己的代碼時,你會知道它是如何發生的。 (一切看起來邏輯音)

使用

使用方法如下:

require(["LibraryA", "LibraryB", "LibraryC"], function() { 
    //code which requires libraries a-c here 
}); 

代碼

var require = (function() { 
    var scriptsLoaded = []; 
    return function(paths, callback) { 
     var pathsDoneLoading = {}; 
     for(var i = 0; i < paths.length; i++) { 
      pathsDoneLoading[paths[i]] = false; 
     } 
     for(var p in pathsDoneLoading) { 
      for(var i = 0; i < scriptsLoaded.length; i++) { 
       if(p === scriptsLoaded[i]) { 
        pathsDoneLoading[p] = true; 
       } 
      } 
     } 
     for(var p in pathsDoneLoading) { 
      if(pathsDoneLoading[p] === false) { 
       var script = document.createElement("script"); 
       script.src = p + ".js"; 
       script.onload = function() { 
        scriptsLoaded.push(p); 
        pathsDoneLoading[p] = true; 
        for(var p in pathsDoneLoading) { 
         if(pathsDoneLoading[p] !== true) { 
          return; 
         } 
        } 
        callback(); 
       }; 
       document.documentElement.appendChild(script); 
      } 
     } 
    } 
})(); 

Plunker

https://plnkr.co/edit/OFWTUpmV3sIJAjhGhcLO

+0

在創建所有腳本元素後,不應該調用回調嗎?現在看起來你想在每個腳本加載後調用它 –

+1

你正在將'require'定義爲一個自動執行的方法嗎?考慮到放棄後面的'();' – Sean3z

+0

我的想法是,「如果其中一個路徑沒有完成就返回」,這導致我假設「如果我們在這裏做出默認回調」 –

回答

2

這是舊的for循環變量捕捉問題。

在循環中,它正在迭代正在加載的路徑(for (var p in pathsDoneLoading) {),p正在綁定到裏面的函數。的問題是,p改變和仍然存在的迴路具有完整所以每單功能是增加在pathsDoneLoading對象的最後關鍵scriptsLoaded陣列(和在pathsDoneLoading設置的匹配值到true)之後。

問題的一個例子:

var obj = { a: 1, b: 2, c: 3 }; 
 
var funcs = []; 
 
for (var key in obj) { 
 
    funcs.push(function() { 
 
    return key; // Remember, `key` is bound to the function, not the block 
 
    }); 
 
} 
 

 
funcs.forEach(function(f) { 
 
    document.querySelector('pre').innerText += f() + '\n'; 
 
});
<pre></pre>

爲了解決這個問題,你可以用它在IIFE每p值來創建一個新的綁定。

for (var p in pathsDoneLoading) { 
    (function(p) { 
    if (pathsDoneLoading[p] === false) { // or `if (!pathsDoneLoading[p])` 
    ... 
    })(p); 
} 

這樣,每次你產生onload處理程序,他們有一個獨特的結合到目標路徑。

我們前面的例子固定用此解決方案:

var obj = { a: 1, b: 2, c: 3 }; 
 
var funcs = []; 
 
for (var key in obj) { 
 
    (function(key) { 
 
    funcs.push(function() { 
 
     return key; // Remember, `key` is bound to the function, not the block 
 
    }); 
 
    })(key); 
 
} 
 

 
funcs.forEach(function(f) { 
 
    document.querySelector('pre').innerText += f() + '\n'; 
 
});
<pre></pre>

0

簡單地說,你需要捕捉的循環迭代,因爲它是一個移動的目標和時間的onload火災,它將會改變。

var require = (function() { 
    var scriptsLoaded = []; 
    return function(paths, callback) { 
     var pathsDoneLoading = {}; 
     for(var i = 0; i < paths.length; i++) { 
      pathsDoneLoading[paths[i]] = false; 
     } 
     for(var p in pathsDoneLoading) { 
      for(var i = 0; i < scriptsLoaded.length; i++) { 
       if(p === scriptsLoaded[i]) { 
        pathsDoneLoading[p] = true; 
       } 
      } 
     } 
     for(var p in pathsDoneLoading) { 
      if(pathsDoneLoading[p] === false) { 
       var script = document.createElement("script"); 
       script.src = p + ".js"; 

       // Wrapping in a closure 
       script.onload = (function(Vp) { 
        scriptsLoaded.push(Vp); 
        pathsDoneLoading[Vp] = true; 
        for(var prop in pathsDoneLoading) { 
         if(pathsDoneLoading[prop] !== true) { 
          return; 
         } 
        } 
        callback(); 

       // Execute the closure function and send in your 
       // var(s) as argument(s) to capture it's current state 
       }(p)); 
       document.documentElement.appendChild(script); 
      } 
     } 
    } 
})(); 
+0

感謝您的回答。順便說一下,當你調用'onload' IIFE,並且你的'(p)'參數語法不正確時,你沒有返回任何東西,但是我在其他代碼中實現了這個解決方案,並且它工作正常。 –

+0

很酷。只是試圖讓事情變得簡單,而不是覆蓋原來的代碼。 Javascript是相當寬容的。要關注的一點是Vp關係。 – bob

相關問題