• nw.js桌面程序自动更新(node.js表白记)


    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('<span style="font-size: 5em;">'+ t-- +'</span>');
                    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('<span style="font-size: 5em;">'+ t-- +'</span>');
                                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!

  • 相关阅读:
    c++MMMMM:oo
    pytorch简单框架
    第95:PCA
    P1:天文数据获取
    深度学习常用函数记录(tensorflow)
    流畅的python(一)序列构成的数组
    tensorflow2.0学习笔记(一)
    BiseNet阅读总结
    DenseASPP论文总结
    论文写作总结
  • 原文地址:https://www.cnblogs.com/BGOnline/p/6291242.html
Copyright © 2020-2023  润新知