Hello Google
Node.js 一个基于Google V8 的JavaScript引擎。
一个伟大的端至端语言,或许我对你的热爱源自于web这门极富情感的技术吧!
注:
光阴似水,人生若梦,又是人间年尾。许久未说过如此矫情而生硬的话- -
如此篇幅实在无法写明白我扭曲的心理,2017望我还能继续迈进!
喜庆的话不多说,今天给大家分享一个大致3周前,初次涉足Node.js实现的nw.js桌面程序的自动更新模块吧。
本文不做教学,仅用于打脸!希望以此得到各位大神的帮助。
我本没有打算写如此博客来误人子弟,这里感谢@老毕(=^ ^=)
下面说的这个模块是基于angular.js的,如此粗鄙的几行代码,还望各位同仁瞄眼之后便使劲的喷!
一、机制分析
此机制的优劣性暂且不议,这仅是目前我唯一能想到的!
已经说了太多无聊的话,这个机制我就画个简单的草图来呈现吧。
从图中不难看出,我所谓的这个自动更新机制其实仅4步而已:
1.确定本地版本号与远端版本号
2.检测版本与平台
3.判断版本差异性
4.是否存在差异的进一步处理
二、模块实现
1.模块依赖
fs = require("fs");path = require("path");request = require("request");child_process = require("child_process");
以下为依赖模块的简要释义:
fs: node.js 文件系统模块
path: node.js 文件路径模块
request: node.js http模块
child_process: node.js 子进程模块
2.版本对比(使用文件读写模块对本地版本号的写入与更新)
compareVer: function(RequestUrl) { var remoteURL = RequestUrl; var deferred = $q.defer(); fs.readFile(path.join(nwDir, "version.txt"), function(err, data) { if(err) { fs.writeFile(path.join(nwDir, "version.txt"), "0.0.1", function(err) { if(err) throw err; }); alert("系统检测到重要文件丢失,请手动重启应用!");
process.exit(0); }else { version.localVer = data; $http.get(remoteURL).success(function(items) { if(items.code == 200) { version.remoteVer = items.data.version; var isUpdate = version.localVer && version.remoteVer && version.localVer != version.remoteVer ? true : false; items.isUpdate = isUpdate; if(isUpdate) { fs.writeFile(path.join(nwDir, "version.txt"), version.remoteVer, function(err) { if(err) throw err; }); } deferred.resolve(items); } }).error(function(data, status, headers, config) { alert("程序初始化失败,请检查网络连接!"); }); } }); return deferred.promise;},
3.执行升级(使用http模块对差异版进行下载并执行文件流写入操作)
update: function(DownloadUrl, total) { request(DownloadUrl, function (error, response) { if(!error && response.statusCode == 200) { angular.element(".title").html("升级完成"); angular.element("#progress > span").html("100"); $interval.cancel(timer); var t = 3; var interval = $interval(function() { angular.element(".title").html("自动重启"); angular.element("#progress").html(""+ t-- +""); if(t < 0) { win.hide() child_process.exec(file, function(err, stdout, stderr) { process.exit(0); }); $interval.cancel(interval); } }, 1000) } }).pipe(fs.createWriteStream(file)); var timer = $interval(function() { var loaded = fs.statSync(file).size; var percentComplete = loaded / total; var downloadProgress = (percentComplete * 100).toFixed(1); angular.element("#progress > span").html(downloadProgress); }, 100); return;}
4.无差异性处理(隐藏主进程并创建子进程)
normal: function() { win.hide(); child_process.exec(file, function(err, stdout, stderr) { process.exit(0); });},
三、完整模块代码
/* nw.js桌面程序自动更新module for angular Author: BGONLINE 2016-12-29*/(function(angular, factory) { if(typeof define === "function" && define.amd) { define("bgo-update", ["angular"], function(angular) { return factory(angular); }); }else { return factory(angular); }}(typeof angular === "undefined" ? null : angular, function(angular) {var module = angular.module("bgoUpdate", []);"use strict";module .factory("bgoAutoUpdate", ["$http", "$q", "$interval", "$timeout", function($http, $q, $interval, $timeout) { var version = { localVer: "", remoteVer: "" } var fs = require("fs"); var path = require("path"); var request = require("request"); var child_process = require("child_process"); var nwPath = process.execPath; var nwDir = path.dirname(nwPath); var file = path.join(nwDir, "current.exe"); return { normal: function() { var str = ""; var interval = $interval(function() { str += "."; angular.element("#progress > span").html(str); if(str.length > 3) { win.hide() child_process.exec(file, function(err, stdout, stderr) { process.exit(0); $interval.cancel(interval); }); } }, 1000) }, compareVer: function(RequestUrl) { var remoteURL = RequestUrl; var deferred = $q.defer(); fs.readFile(path.join(nwDir, "version.txt"), function(err, data) { if(err) { fs.writeFile(path.join(nwDir, "version.txt"), "0.0.1", function(err) { if(err) throw err; }); layer.alert("系统检测到重要文件丢失,请手动重启应用!", {closeBtn: 0, icon: 5, shade: 0}, function() { layer.closeAll(); process.exit(0); }); }else { version.localVer = data; $http.get(remoteURL).success(function(items) { if(items.code == 200) { version.remoteVer = items.data.version; var isUpdate = version.localVer && version.remoteVer && version.localVer != version.remoteVer ? true : false; items.isUpdate = isUpdate; if(isUpdate) { fs.writeFile(path.join(nwDir, "version.txt"), version.remoteVer, function(err) { if(err) throw err; }); } deferred.resolve(items); } }).error(function(data, status, headers, config) { layer.msg("程序初始化失败,请检查网络连接!", function() {}); }); } }); return deferred.promise; }, update: function(DownloadUrl, total) { request(DownloadUrl, function (error, response) { if(!error && response.statusCode == 200) { angular.element(".title").html("升级完成"); angular.element("#progress > span").html("100"); $interval.cancel(timer); var t = 3; var interval = $interval(function() { angular.element(".title").html("自动重启"); angular.element("#progress").html(""+ t-- +""); if(t < 0) { win.hide() angular.element(".title").html("学籍系统保护模块"); angular.element("#progress > span").html("请勿关闭!"); child_process.exec(file, function(err, stdout, stderr) { process.exit(0); }); $interval.cancel(interval); } }, 1000) } }).pipe(fs.createWriteStream(file)); var timer = $interval(function() { var loaded = fs.statSync(file).size; var percentComplete = loaded / total; var downloadProgress = (percentComplete * 100).toFixed(1); angular.element("#progress > span").html(downloadProgress); }, 100); return; } } }]) return module;}));
四、模块调用
App.controller("UpdateController", ["$rootScope", "$scope", "bgoAutoUpdate", function($rootScope, $scope, bgoAutoUpdate) { bgoAutoUpdate.compareVer($rootScope.rootUrl + "index/login/getVersion?platform=" + process.platform).then(function(res) { // 判断版本 $scope.isUpdate = res.isUpdate; if($scope.isUpdate) { bgoAutoUpdate.update(res.data.fileUrl, res.data.fileSize, res.data.version); // 执行更新 }else { bgoAutoUpdate.normal(); } }); }]);
如此可爱的node.js,感谢Google!