Мне нужно сделать запрос на один и тот же сервер, отдохнуть api на другом порту.
Как я могу сделать это без полного имени hardcoding в служебных URL-адресах?
Мне нужно сделать запрос на один и тот же сервер, отдохнуть api на другом порту.
Как я могу сделать это без полного имени hardcoding в служебных URL-адресах?
Нет необходимости в угловом2-специфичном решении. Вы можете использовать window.location.hostname
для получения текущего имени хоста.
Обратите внимание, однако, что если вы не хотите использовать глобальные переменные, такие как window
-object напрямую, вы можете предоставить свой собственный объект Window
, который затем можно внедрить.
См. Этот полный рабочий образец углового Stackblitz для деталей.
Как уже говорили другие, оригинальный ответ больше не работает. Для Angular 6+ необходимо предоставить токен впрыска, чтобы window
-object можно было разрешить и в AOT -build.
Я рекомендую создать массив WINDOW_PROVIDERS
в отдельном файле, например:
import { InjectionToken, FactoryProvider } from '@angular/core';
export const WINDOW = new InjectionToken<Window>('window');
const windowProvider: FactoryProvider = {
provide: WINDOW,
useFactory: () => window
};
export const WINDOW_PROVIDERS = [
windowProvider
]
Константу WINDOW_PROVIDERS
можно добавить в массив providers
в AppModule
следующим образом:
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [
WINDOW_PROVIDERS, // <- add WINDOW_PROVIDERS here
SampleService,
],
bootstrap: [AppComponent]
})
export class AppModule { }
В SampleService
window
объект может быть внедрен с использованием определенного токена инъекции следующим образом:
import { Injectable, Inject } from '@angular/core';
import { WINDOW } from '../window.provider';
@Injectable()
export class SampleService {
constructor(@Inject(WINDOW) private window: Window) {
}
getHostname() : string {
return this.window.location.hostname;
}
}
Поэтому вам нужно установить провайдера для Window
-object при загрузке вашего приложения.
import {provide} from 'angular2/core';
bootstrap(..., [provide(Window, {useValue: window})]);
После этого вы можете использовать объект окна и получить доступ к имени хоста следующим образом:
constructor(private window: Window) {
var hostname = this.window.location.hostname;
}
Другой вариант - использовать DOCUMENT из @angular/platform-browser.
import {DOCUMENT} from '@angular/platform-browser';
constructor(@Inject(DOCUMENT) private document: Document) {
let url = document.location.protocol +'//'+ document.location.hostname + ':my_port' );
}
Angular 2 последнее рабочее решение:
app.module.ts
providers: [
{provide: Window, useValue: window},
...
]
youclass.ts
constructor(
@Inject(Window) private _window: Window
) {
this._baseUrl = `http://${this._window.location.hostname}:3333`;
};
Вы можете использовать window
, как заявили другие, и чтобы сделать его инъекционным, начиная с ng6 и выше, вам нужен токен инъекции.
Объявите токен так:
export const WINDOW = new InjectionToken('window',
{ providedIn: 'root', factory: () => window }
);
Затем используйте его в конструкторе класса:
class Foo {
constructor(@Inject(WINDOW) private window: Window) { }
}
Поскольку Window
- это интерфейс в TypeScript, если вы не сделаете инъекцию подобным образом, при создании проекта для производства вы получите ошибку: Can't resolve all parameters for <ClassName>
удается Can't resolve all parameters for <ClassName>
. А потом еще: ERROR in: Error: Internal error: unknown identifier undefined
.
Чтобы лучше понять инъекцию, прочитайте угловые документы для DI: https://angular.io/guide/dependency-injection
Я достиг этого с помощью следующего кода в app.component.ts
:
import { Component, OnInit, Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(@Inject(DOCUMENT) private document: any) { }
ngOnInit() {
this.domain = this.document.location.hostname;
console.log(this.domain);
}
}
Это должно печатать имя домена в консоли.
Я рекомендую использовать window.location
, как прокомментировали другие.
Однако вы также можете сделать это, импортировав библиотеку Angular common 'Location' и используя ее для инъекции следующим образом:
import { Injectable } from '@angular/core';
import { Location } from '@angular/common';
const otherPort = 8000;
@Injectable()
export class ServiceOrComponentName {
constructor(location: Location) {
this.baseUrl = location._platformStrategy._platformLocation._location.protocol +
'//' + location._platformStrategy._platformLocation._location.hostname +
':' + otherPort;
}
}
Я проверяю это на Angular 7, и он работал правильно
declare var window: any;
console.log (window.location.host); //result lrlucas.github.io > domain github pages
с window.location.host я получаю полный домен
Примечание. @Component
переменную окна перед @Component
Это должно помочь вам:
import {LocationStrategy} from '@angular/common';
constructor(private locationStrategy:LocationStrategy) {
console.log(locationStrategy.prepareExternalUrl('xxx'));
}
Я использую простой JavaScript и URL нативного API для анализа URL:
const parsedUrl = new URL(window.location.href);
const baseUrl = parsedUrl.origin;
console.log(baseUrl); // this will print http://example.com or http://localhost:4200