对于循环触发超出所需

时间:2019-03-06 12:12:47

标签: javascript

我正在尝试向此homepage project添加快速启动功能,该功能将通过按键来启动所有quickLaunch属性设置为true的URL。

我已经通过向CONFIG对象添加quickLaunch属性来设置场景,如下所示:

const CONFIG = {
    commands: [{
        {
            category: 'General',
            name: 'Mail',
            key: 'm',
            url: 'https://gmail.com',
            search: '/#search/text={}',
            color: 'linear-gradient(135deg, #dd5145, #dd5145)',
            icon: 'mail.png',
            quickLaunch: true,
        },
        {
            category: 'General',
            name: 'Drive',
            key: 'd',
            url: 'https://drive.google.com',
            search: '/drive/search?q={}',
            color: 'linear-gradient(135deg, #FFD04B, #1EA362, #4688F3)',
            icon: 'drive.png',
            quickLaunch: false,
        },
        {
            category: 'Tech',
            name: 'GitHub',
            key: 'g',
            url: 'https://github.com',
            search: '/search?q={}',
            color: 'linear-gradient(135deg, #2b2b2b, #3b3b3b)',
            icon: 'github.png',
            quickLaunch: true,
        },

...and so on

,然后添加一个条件以启动所有启用了quickLaunch选项的网站:

class QueryParser {
    constructor(options) {
        this._commands = options.commands;
        this._searchDelimiter = options.searchDelimiter;
        this._pathDelimiter = options.pathDelimiter;
        this._protocolRegex = /^[a-zA-Z]+:\/\//i;
        this._urlRegex = /^((https?:\/\/)?[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?)$/i;
        this.parse = this.parse.bind(this);
    }

    parse(query) {
        const res = {
            query: query,
            split: null
        };

        if (this._urlRegex.test(query)) {
            const hasProtocol = this._protocolRegex.test(query);
            res.redirect = hasProtocol ? query : 'http://' + query;
        } else {
            const trimmed = query.trim();
            const splitSearch = trimmed.split(this._searchDelimiter);
            const splitPath = trimmed.split(this._pathDelimiter);

            this._commands.some(({
                category,
                key,
                name,
                search,
                url,
                quickLaunch
            }) => {
                if (query === key) {
                    res.key = key;
                    res.isKey = true;
                    res.redirect = url;
                    return true;
                }

                if (splitSearch[0] === key && search) {
                    res.key = key;
                    res.isSearch = true;
                    res.split = this._searchDelimiter;
                    res.query = QueryParser._shiftAndTrim(splitSearch, res.split);
                    res.redirect = QueryParser._prepSearch(url, search, res.query);
                    return true;
                }

                if (splitPath[0] === key) {
                    res.key = key;
                    res.isPath = true;
                    res.split = this._pathDelimiter;
                    res.path = QueryParser._shiftAndTrim(splitPath, res.split);
                    res.redirect = QueryParser._prepPath(url, res.path);
                    return true;
                }

                if (key === '*') {
                    res.redirect = QueryParser._prepSearch(url, search, query);
                }

/* ---> */      if (query === 'q!') {
                    for (let i = 0; i < this._commands.length; i++) {
                        if (this._commands[i].quickLaunch === true) {
                            window.open(this._commands[i].url);
                        }
                    }
                    return true;
                }
            });
        }

        res.color = QueryParser._getColorFromUrl(this._commands, res.redirect);
        return res;
    }

    static _getColorFromUrl(commands, url) {
        const domain = new URL(url).hostname;

        return (
            commands
            .filter(c => new URL(c.url).hostname.includes(domain))
            .map(c => c.color)[0] || null
        );
    }

    static _prepPath(url, path) {
        return QueryParser._stripUrlPath(url) + '/' + path;
    }

    static _prepSearch(url, searchPath, query) {
        if (!searchPath) return url;
        const baseUrl = QueryParser._stripUrlPath(url);
        const urlQuery = encodeURIComponent(query);
        searchPath = searchPath.replace('{}', urlQuery);
        return baseUrl + searchPath;
    }

    static _shiftAndTrim(arr, delimiter) {
        arr.shift();
        return arr.join(delimiter).trim();
    }

    static _stripUrlPath(url) {
        const parser = document.createElement('a');
        parser.href = url;
        return `${parser.protocol}//${parser.hostname}`;
    }
}

我希望标记的条件(带有“->”注释)仅触发一次,但整个过程将执行四次。我记录了它试图启动的URL,看起来像这样:

log

我缺少一个明显的核心概念吗?

1 个答案:

答案 0 :(得分:2)

好像this._commands.some(贯穿您的所有this._commands,然后您检查查询是否为query === 'q!',我想那总是对的,如果是这样,那么您就遍历{{1} }。给您this._commands的输出量。