Сделайте вызов Api из углового компонента - PullRequest
0 голосов
/ 24 сентября 2018

Я новичок в Angular, но сейчас я хотел бы создать компонент для анализа всех медиа-запросов из внутренних таблиц стилей, а также внешних и вывода их.Чтобы обработать все @import s, я должен сделать запрос к внешним таблицам стилей с помощью метода fetchStyleSheetText():

// ...

export class MediaQueriesWidgetComponent implements OnInit, OnChanges {
  @Input() content;
  @Input() isContentLoading;

  mediaQueriesList = [];

  mediaReg: RegExp = /@media[^{]+ /g;
  importReg: RegExp = /@import url\("(.+)"\) /g;

  constructor(private cd: ChangeDetectorRef,
          private _ApiService: ApiService) { }


  ngOnInit(): void {
    //this.fetchStyleSheetText();
  }

  ngOnChanges(changes: SimpleChanges) {
    const contentChanges = changes.content;
    if (contentChanges) {
      const currentContent = contentChanges.currentValue && contentChanges.currentValue.content;
      const element = this.parseHtml(currentContent), styleSheetsSelector = 'style,[style],link[rel*="stylesheet"]';
      const styleSheets = this.getStyleSheets(element, styleSheetsSelector);
      console.log(styleSheets);
      this.mediaQueriesList = this.styleSheetsReducer(styleSheets);
   }

   parseHtml(html: string): DocumentFragment | HTMLTemplateElement {
     const el = document.createElement('template');
     el.innerHTML = html;

     return el.content || el;
   }

   private getStyleSheets(element: DocumentFragment | HTMLTemplateElement, selector: string): Element[] {
     return Array.from(element.querySelectorAll(selector));
   }

   private parseStyleSheetText(text: string): string[] {
     let match: RegExpExecArray;
     const importRules = [];
     const mediaQueries = text.match(this.mediaReg) || [];
     console.log(mediaQueries);
     while (match = this.importReg.exec(text)) {
       importRules.push(match[1]);
     }

     return importRules.reduce((result: string[], url: string) => {
       return result.concat(this.fetchStyleSheetText(url));
     }, mediaQueries.map(query => query.trim()));
   }

   private fetchStyleSheetText(url: string): string[] {
      // const requestedCssText= this._ApiService.getFromApi(url, ActionType.webfiles, true));
      // return this.parseStyleSheetText(requestedCssText);
   }

   styleSheetsReducer(styleSheets: Element[]): string[] {
     return styleSheets.reduce((result: string[], element: any) => {
       switch (element.localName) {
         case 'style':
           return result.concat(this.parseStyleSheetText(element.innerHTML));
         case 'link':
           return result.concat(this.fetchStyleSheetText(element.href));
         default:
           return result.concat(this.parseStyleSheetText(element.style.cssText));
         }
       }, []);
     }
   }

Для загрузки Id внешнего стиля хотелось бы использовать метод fetchStyleSheetText() и передать ответ на parseStyleSheetText()но я не знаю, как реализовать fetchStyleSheetText (), возможно, мне нужен хук жизненного цикла, например ngOnInit().

Я собираюсь использовать уже существующий Api-сервис:

   import { HttpClient } from '@angular/common/http';
   import { Injectable } from '@angular/core';
   import { environment } from 'environments/environment';
   import { BehaviorSubject, Observable } from 'rxjs';
   import { shareReplay, take } from 'rxjs/operators';

   export enum ActionType {
     'content' = 'content',
     'metatags' = 'metatags',
     'microdata' = 'microdata',
     'social' = 'social',
     'httpdata' = 'httpdata',
     'webfiles' = 'webfiles',
     'whois' = 'whois',
     'audience' = 'audience',
     'mozdata' = 'mozdata',
     'alexa' = 'alexa',
     'google' = 'google',
     'headers' = 'headers'
    }

    @Injectable()
    export class ApiService {
      private key: string;
      private cache: {[propName: string]: [Observable<any>, string]} = {};
      private loadingMap: {[propName: string]: BehaviorSubject<boolean>} = 
        {};

      constructor(private http: HttpClient) {

        this.loadingMap = Object.entries(ActionType)
          .reduce((res, [key]) => ({...res, [key]: new BehaviorSubject(false)}), {});
      }

      getFromApi(url: string, type: ActionType, force?: boolean) {
        let [obs$ = null, cacheUrl = ''] = this.cache[type] || [];

        if (!obs$ || cacheUrl !== url || force) {
          cacheUrl = url;
          obs$ = this.makeRequest(url, type).pipe(
          shareReplay(1)
        );
        this.processLoading(obs$, type);
        this.cache[type] = [obs$, cacheUrl];
      }

      return obs$;
    }

    makeRequest(url: string, type: ActionType) {
      return this.http.jsonp(this.getEndpoint(url, type), 'jsonp');
    }

    private getEndpoint(url, type) {
      const params = new URLSearchParams();
      params.set('key', this.key);
      params.set('url', url);

      let apiUrl = 'api.someurl.com';
      if ('alexa' === type) {
        apiUrl = 'www.someurl.com/api';
      }
      return `https://${apiUrl}/v1/${type}?${params.toString()}`;
    }
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...