2015-09-09 24 views
2

我一直在玩Chromes filestorage API。我已經構建了幾個函數,它們一起自動下載一個json對象並將其作爲字符串存儲。如果最後一次服務器請求在24小時內完成。我自動使用該文件的最新版本。我使用它來管理我做統計分析的龐大數據轉儲。我寫了一些殺人的Javascript。我怎樣才能使它容易重用?

整個系統只有一個功能需要暴露。這是getData

目前所有這些功能都是全局變量。我應該如何以有條不紊的方式來做到這一點。

//This file will cache serverdata every day. 
var onInitFs, 
errorHandler, 
fileSystemInit, 
saveFile, 
readFile, 
fileSystem, 
getData; 


//request rights to save files to system. 
fileSystemInit = function(){ 
    //Browser specific 
    window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; 

    navigator.webkitPersistentStorage.requestQuota(1048*1048*256, function(grantedBytes) { 
     //once approved (or if previously approved): 
     window.requestFileSystem(PERSISTENT, grantedBytes, onInitFs, errorHandler); 
    }, function(e) { 
    console.log('Error', e); 
    }); 
}; 

//make filesystem global. 
onInitFs = function(fs) { 
    fileSystem = fs; 
}; 
fileSystemInit(); 

saveFile = function(url, content, callback){ 
    var filename = makeFilename(url) 
    if(!fileSystem){ 
     console.log('no filesystem registered') 
     return; 
    } 
    fileSystem.root.getFile(filename, {create: true}, function(fileEntry) { 

     fileEntry.createWriter(function(fileWriter) { 
      var blob = new Blob([JSON.stringify(content)], {type: 'application/json'}); 
      fileWriter.write(blob); 

      fileWriter.onwriteend = function(e) { 
       console.debug('Write completed.', e); 
       if(callback){ 
        callback(); 
       } 
      }; 

      fileWriter.onerror = function(e) { 
       console.log('Write failed: ', e); 
      }; 
     }, errorHandler); 

    }, errorHandler); 
}; 

readFile = function(url, callback){ 
    var filename = makeFilename(url) 
    if(!fileSystem){ 
     console.log('no filesystem registered'); 
     return; 
    } 

    fileSystem.root.getFile(filename, {}, function(fileEntry){ 

     //this object reads files. 
     var reader = new FileReader(); 
     //register callback for read files 
     reader.onloadend = function(e){ 
      var callbackValue = JSON.parse(this.result) 
      callback(callbackValue); 
     }; 
     //read file-function 
     fileEntry.file(function(file){ 
      reader.readAsText(file); 
     },errorHandler); 

    },errorHandler); 
}; 

makeFilename = function(url){ 
    return url.replace(/\W/g, '') +'.json' 
} 

errorHandler = function(e) { 
    console.log('Error: ', e); 
}; 

getData = function(url, callbackNewData, callbackOldData){ 
    var lastDownloaded = localStorage.getItem(url+'lastDownloaded'), 
    oneDay = 1000*60*60*24; 
    //update data if the data is old. 
    window.setTimeout(function(){ 
     if(!lastDownloaded || new Date()-new Date(lastDownloaded) > oneDay){ 
      console.debug('downloading '+url); 
      d3.json(url, function(data){ 
       localStorage.setItem(url+'lastDownloaded',new Date()); 
       console.debug('saving '+url); 
       saveFile(url, data, function(){ 
        callbackNewData(url); 
       }); 
      }); 
     }else{ 
      callbackOldData(url); 
     } 

    }, 200); 
}; 
+0

這可以幫助你:http://bergie.iki.fi/blog/sharing-javascript-libraries-node-browser/ – lex82

+1

(-1),因爲它不值得它已經有了upvote。你正在爲重寫你的代碼尋求意見,雖然你甚至不清楚你在找什麼。只是「讓它變得更好」,這意味着什麼也沒有 – musefan

+1

另外我認爲http://codereview.stackexchange.com更適合這個。 – FelisCatus

回答

2

你可以把整個事情包裝在一個匿名函數中,只公開getData。這是最簡單的方法。

var getDataFromUrl = function() { 
    //This file will cache serverdata every day. 
    var onInitFs, 
    errorHandler, 
    fileSystemInit, 
    saveFile, 
    readFile, 
    fileSystem, 
    getData; 

    // Your original code here ... 

    return getData; // This exposes the getData function. 
})(); 

這樣你只能公開一個全局函數getDataFromUrl,這正是公共API。

更多現代用法,你可能想看看Common JS ModulesBrowserify,讓您在瀏覽器和做的NodeJS和exportsrequire。還有一個用於導出庫的UMD Pattern

+1

或者只是將getData聲明爲不帶'var'的全局變量。 – slebetman

+0

這與製作像這樣的模塊相比如何? http://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript – Himmators

+1

@Himmators這個答案是像_The模塊Pattern_書中,使用的包裝和隱私IIFE。本書中的CommonJS模塊也在上面的答案中提到。本書的其他章節包括對象文字,AMD和Harmony模塊,這不是這裏的主題。長時間比較所有這些模式並不適合答案。他們應該在網上其他地方的書中討論。 – FelisCatus

0
(function(window){ 
'use strict' 
var onInitFs,errorHandler,fileSystemInit,saveFile,readFile,fileSystem,getData; 

fileSystemInit = function(){ 
    // your code 
}; 
//make filesystem global. 
onInitFs = function(fs) { 
    //your code 
}; 
fileSystemInit(); 

saveFile = function(url, content, callback){ 
    //your code 
}; 

readFile = function(url, callback){ 
    //your code 
}; 

makeFilename = function(url){ 
    //your code 
} 

errorHandler = function(e) { 
    //your code 
}; 

getData = function(url, callbackNewData, callbackOldData){ 
    //your code 
}; 

window.HimmatorsFileStorageAPI = getData; // you can change the name here 

})(window); 

你可以簡單的通過在你的頁面這個腳本,然後調用

HimmatorsFileStorageAPI(url, callbackNewData, callbackOldData);

0

只需將原型製作出來即可:-)並使用一些有作用域的實例(使用var that = this)將元素傳遞回來自不同作用域的父對象。

現在你可以開始一個new FileSystemInstance()做你的魔力。

如果你想讓更多的「奧術」方法是私人的,你可以考慮將它們移動到物體內的物體等等,但最終有真正的毅力的人將能夠訪問它們。所以我建議採用公開的方式,並命名私有方法_fileSystemInit,以便閱讀代碼的人員知道這是一種內部化的方法。

//This file will cache serverdata every day. 
 

 
function FileSystemInstance() { 
 
    this.fileSystem = null; 
 
    this.requestFileSystem = null; 
 
    
 
    this.fileSystemInit(); 
 
    
 
    
 
} 
 
//request rights to save files to system. 
 
FileSystemInstance.prototype.fileSystemInit = function(){ 
 
    //Browser specific 
 
    this.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; 
 
    this.requestFileSystem = this.requestFileSystem.bind(window); 
 
    console.log(this.requestFileSystem); 
 
\t var that = this; 
 
    console.log(that.requestFileSystem); 
 
    navigator.webkitPersistentStorage.requestQuota(1048*1048*256, function(grantedBytes) { 
 
     //once approved (or if previously approved): 
 
     console.log(that.requestFileSystem); 
 
     that.requestFileSystem(PERSISTENT, grantedBytes, function(fs){that.onInitFs(fs)}, function(e){that.errorHandler(e)}); 
 
    }, function(e) { 
 
    console.log('Error', e); 
 
    }); 
 
}; 
 

 
//make filesystem global. 
 
FileSystemInstance.prototype.onInitFs = function(fs) { 
 
    this.fileSystem = fs; 
 
}; 
 

 

 
FileSystemInstance.prototype.saveFile = function(url, content, callback){ 
 
    var filename = this.makeFilename(url) 
 
    if(!fileSystem){ 
 
     console.log('no filesystem registered') 
 
     return; 
 
    } 
 
    this.fileSystem.root.getFile(filename, {create: true}, function(fileEntry) { 
 

 
     fileEntry.createWriter(function(fileWriter) { 
 
      var blob = new Blob([JSON.stringify(content)], {type: 'application/json'}); 
 
      fileWriter.write(blob); 
 

 
      fileWriter.onwriteend = function(e) { 
 
       console.debug('Write completed.', e); 
 
       if(callback){ 
 
        callback(); 
 
       } 
 
      }; 
 

 
      fileWriter.onerror = function(e) { 
 
       console.log('Write failed: ', e); 
 
      }; 
 
     }, errorHandler); 
 

 
    }, errorHandler); 
 
}; 
 

 
FileSystemInstance.prototype.readFile = function(url, callback){ 
 
    var filename = this.makeFilename(url) 
 
    if(!this.fileSystem){ 
 
     throw new Error('no filesystem registered'); 
 
    } 
 

 
    this.fileSystem.root.getFile(filename, {}, function(fileEntry){ 
 

 
     //this object reads files. 
 
     var reader = new FileReader(); 
 
     //register callback for read files 
 
     reader.onloadend = function(e){ 
 
      var callbackValue = JSON.parse(this.result) 
 
      callback(callbackValue); 
 
     }; 
 
     //read file-function 
 
     fileEntry.file(function(file){ 
 
      reader.readAsText(file); 
 
     },errorHandler); 
 

 
    },errorHandler); 
 
}; 
 

 
FileSystemInstance.prototype.makeFilename = function(url){ 
 
    return url.replace(/\W/g, '') +'.json' 
 
} 
 

 
FileSystemInstance.prototype.errorHandler = function(e) { 
 
    console.error('Error: ', e); 
 
}; 
 

 
FileSystemInstance.prototype.getData = function(url, callbackNewData, callbackOldData){ 
 
    var that = this; 
 
    var lastDownloaded = localStorage.getItem(url+'lastDownloaded'), 
 
    oneDay = 1000*60*60*24; 
 
    //update data if the data is old. 
 
    window.setTimeout(function(){ 
 
     if(!lastDownloaded || new Date()-new Date(lastDownloaded) > oneDay){ 
 
      console.debug('downloading '+url); 
 
      d3.json(url, function(data){ 
 
       localStorage.setItem(url+'lastDownloaded',new Date()); 
 
       console.debug('saving '+url); 
 
       that.saveFile(url, data, function(){ 
 
        callbackNewData(url); 
 
       }); 
 
      }); 
 
     }else{ 
 
      callbackOldData(url); 
 
     } 
 

 
    }, 200); 
 
}; 
 
FileSystem = new FileSystemInstance(); 
 
var data = FileSystem.getData(); 
 
console.log("Data is: ",data);