首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >总结和爬行URL的内容

总结和爬行URL的内容
EN

Code Review用户
提问于 2016-11-28 18:17:31
回答 1查看 105关注 0票数 3

最近,为了更好地理解JS ES6,我一直在从事一个使用JS ES6的实践项目,因此我阅读了很多关于JS设计模式和JS编码策略的文章。我的问题是如何分割项目的功能,所以我必须简单地解释一下我在这个项目中要做什么。

我有一个输入,它得到一个带有页面URL的命令。命令是summarizecrawlsummarize实际上总结了给定URL的内容,并抓取URL中的单词。

代码语言:javascript
复制
class App {

    constructor(options) {
        this.email = options.email;
        this.inputElement = options.inputElement;
        this.progressElement = options.progressElement;
        this.infoElement = options.infoElement;
        this.outputElement = options.outputElement;
        this.init();
    }

    init() {
        this.socket = io();
        this.socket.emit('join', {email: this.email});
        this.progress = {
            action: document.querySelector('.progress-action'),
            percentage: document.querySelector('.progress-percentage'),
            bar: document.querySelector('.progress-bar')
        };
        this.bindEvents();
    }

    bindEvents() {
        let that = this;

        this.inputElement.addEventListener('keyup', function (e) {
            if (e.keyCode === 13) {
                let compiledInput = that.tools().compileInput(this.value);
                if (!compiledInput.target) {
                    that.tools().showInfo(that.resources().messages.noURL);
                }
                else if (!compiledInput.command) {
                    that.tools().showInfo(that.resources().messages.noCommand);
                }
                else {
                    that.tools().showInfo(that.resources().messages.syntax);
                    that.progressElement.classList.add('show');
                    that.action()[compiledInput.command](compiledInput);
                }
            }
            else if (this.value.trim() !== '') {
                that.tools().showInfo(that.resources().messages.pressEnter);
            }
            else {
                that.tools().showInfo(that.resources().messages.syntax);
            }
        });

        that.socket.on('crawlProcess', function (resp) {
            that.progress.action.innerHTML = resp.action;
            that.progress.percentage.innerHTML = resp.index + ' Files Crawled - ' + resp.percentage + '%';
            that.progress.bar.style.width = resp.percentage + '%';

            that.outputElement.innerHTML = '';
            for (let i = 0; i < resp.response.length; i++) {
                let fieldKey = Object.keys(resp.response[i])[0];
                let fields = '<span class="word">' + resp.response[i][fieldKey] + '</span>';
                that.outputElement.insertAdjacentHTML('beforeend', fields);
            }

            if (parseInt(resp.percentage) === 100) {
                setTimeout(()=> {
                    that.progressElement.classList.remove('show');
                    if (that.outputElement.innerHTML.trim() === '') {
                        that.tools().showInfo(that.resources().messages.alreadyCrawled);
                    }
                    else {
                        that.outputElement.classList.add('show');
                    }
                }, 500);
            }
        });

        that.socket.on('summarize', function (resp) {
            that.progress.action.innerHTML = resp.action;
            that.progress.percentage.innerHTML = resp.percentage + '%';
            that.progress.bar.style.width = resp.percentage + '%';
            if (parseInt(resp.percentage) === 100) {
                setTimeout(()=> {
                    if (!resp.error) {
                        that.outputElement.innerHTML = resp.response;
                        that.outputElement.classList.add('show');
                    }
                    else {
                        that.outputElement.innerHTML = '';
                        that.outputElement.classList.remove('show');
                        that.tools().showInfo(resp.response.message);
                    }
                    that.progressElement.classList.remove('show');
                }, 500);
            }
        });
    }

    action() {
        let that = this;
        return {
            crawl(options){
                that.socket.emit(options.command, {
                    url: options.target,
                    maxCrawlCount: options.option || 10,
                    includeAbsolute: true
                });
            },
            summarize(options){
                that.socket.emit(options.command, {
                    url: options.target,
                    paragraphs: options.option || 1
                });
            }
        }
    }

    resources() {
        return {
            messages: {
                pressEnter: 'Press enter to go!',
                noURL: 'Please provide a valid target URL to act on!',
                noCommand: 'Command not found!',
                syntax: 'What can I do for you?',
                alreadyCrawled: 'This page is already crawled!'
            },
            commands: ['summarize', 'crawl']
        }
    }

    tools() {
        let that = this;
        return {
            levenshteinDistance(a, b) {
                if (a.length == 0) return b.length;
                if (b.length == 0) return a.length;

                let matrix = [];

                // increment along the first column of each row
                let i;
                for (i = 0; i <= b.length; i++) {
                    matrix[i] = [i];
                }

                // increment each column in the first row
                let j;
                for (j = 0; j <= a.length; j++) {
                    matrix[0][j] = j;
                }

                // Fill in the rest of the matrix
                for (i = 1; i <= b.length; i++) {
                    for (j = 1; j <= a.length; j++) {
                        if (b.charAt(i - 1) == a.charAt(j - 1)) {
                            matrix[i][j] = matrix[i - 1][j - 1];
                        } else {
                            matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
                                Math.min(matrix[i][j - 1] + 1, // insertion
                                    matrix[i - 1][j] + 1)); // deletion
                        }
                    }
                }

                return matrix[b.length][a.length];
            },

            levenshteinPercentage(a, b) {
                return 1 - (1 / (Math.max(a.length, b.length)) * that.tools().levenshteinDistance(a, b));
            },

            compileInput (input) {
                let url = that.tools().extractURL(input),
                    command = that.tools().extractCommand(input.replace(url || '', '')),
                    option = input.match(/ \d+/);

                option = (option) ? parseInt(option[0]) : null;

                return {
                    target: url,
                    command: command,
                    option: option
                };
            },

            extractURL (input) {
                let matchedURLs = input.match(/(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/ig);
                return (matchedURLs) ? matchedURLs[0] : null;
            },

            extractCommand (input) {
                let matchedCommands = [];

                input = input.split(' ');

                for (let j = 0; j < that.resources().commands.length; j++) {
                    for (let i = 0; i < input.length; i++) {
                        if (input[i].trim() !== '') {
                            let distance = that.tools().levenshteinPercentage(input[i].toLowerCase(), that.resources().commands[j].toLowerCase());
                            if (distance > .5) {
                                matchedCommands.push({
                                    command: that.resources().commands[j],
                                    distance: distance
                                });
                            }
                        }
                    }
                }

                return that.tools().sortByKeyVal(matchedCommands, 'distance')[0].command;
            },

            sortByKeyVal (arr, key) {
                return arr.sort(function (a, b) {
                    if (a[key] < b[key])
                        return 1;
                    if (a[key] > b[key])
                        return -1;
                    return 0;
                });
            },

            showInfo(message){
                that.infoElement.innerText = message;
            }
        }
    }
}

new App({
    email: 'a.jafari.90@gmail.com',
    inputElement: document.querySelector('.input'),
    progressElement: document.querySelector('.progress'),
    infoElement: document.querySelector('.info'),
    outputElement: document.querySelector('.output')
});

这是一个有效的编码策略,只有一个类,并将函数包装并分组为方法吗?这会使更大的项目变得更复杂吗?如果是这样的话,对于像我当前项目这样的项目,建议的或最佳实践编码策略是什么?

EN

回答 1

Code Review用户

回答已采纳

发布于 2016-12-01 14:55:32

tools(), resources() and actions()都应该静态地实现为Objects,而不是返回对象的函数。否则,每次使用它们时,都会在内存中重新创建它们。

示例:

代码语言:javascript
复制
class App { ... }
App.Tools = { tools code... };
App.Resources = { resources code... };
App.Actions = { actions code };

更进一步说,tools通常称为Utilities,可以在单独的实用程序文件/模块中定义,该文件/模块可以在应用程序中进行引用和重用。特别是如果实用程序包含常用的函数。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/148367

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档