Загрузка JSON без HTTP-запроса
Я работаю над проектом, используя Angular 4, NPM, Node.js и угловой CLI.
У меня есть довольно необычная потребность загрузить JSON в угловой сервис (используя
@Injectable) без HTTP-запроса, то есть он всегда будет загружен локально как часть пакета, а не извлекаться с сервера.Все, что я нашел до сих пор, указывает на то, что вам нужно либо изменить файл проекта typings.d.ts, либо использовать HTTP-запрос для его извлечения из папки /assets или аналогичного, ни один из что для меня тоже вариант.
То, что я пытаюсь выполнить это. Дана следующая структура каталогов:
/app
/services
/my-service
/my.service.ts
/myJson.json
Мне нужна служба my.service.ts, которая использует @Injectable, чтобы загрузить файл JSON myJson.json. В моем конкретном случае рядом с файлом my.service.ts будет находиться несколько файлов JSON, которые все должны быть загружены.
Чтобы прояснить, следующие подходы не будут работать для меня:
Использование службы HTTP для загрузки файла JSON из Assets
URL: https://stackoverflow.com/a/43759870/1096637
Отрывок:
// Get users from the API
return this.http.get('assets/ordersummary.json')//, options)
.map((response: Response) => {
console.log("mock data" + response.json());
return response.json();
}
)
.catch(this.handleError);
Изменение типов.d. ts разрешить загрузку файлов JSON
URL: https://hackernoon.com/import-json-into-typescript-8d465beded79
Отрывок:
Решение: Использование Подстановочного Имени Модуля
В TypeScript версии 2 + мы можем использовать подстановочный знак в имени модуля. В файле определения TS, например typings.d.ts, Вы можете добавить следующую строку:
declare module "*.json" {
const value: any;
export default value;
}
Тогда ваш код будет работать как обаяние!
// TypeScript
// app.ts
import * as data from './example.json';
const word = (<any>data).name;
console.log(word); // output 'testing'
Вопрос
Есть ли у кого-нибудь еще идеи по загрузке этих файлов в мой сервис без необходимости использования любого из этих подходов?
3 ответов:
Вы получите ошибку, если вызовете json напрямую, но простой обходной путь заключается в объявлении типов для всех файлов json.
машинопись.d. ts
declare module "*.json" { const value: any; export default value; }комп.ts
import * as data from './data.json';
Решение, которое я нашел для этого, было с помощью RequireJS, который был доступен мне через Angular CLI framework.
Я должен был объявить require как переменную глобально:
declare var require: any;И затем я мог бы использовать
require.context, чтобы получить все файлы в папке, которую я создал для хранения типов в../types.Пожалуйста, найдите ниже всю завершенную службу, которая загружает все файлы JSON (каждый из которых является типом) в служебную переменную
types.Результатом является объект типы, где ключом для типа является имя файла, а связанным значением-JSON из файла.
Пример результата загрузки файлов
type1.json,type2.json, иtype3.jsonиз папки../types:{ type1: { class: "myClass1", property1: "myProperty1" }, type2: { class: "myClass2", property1: "myProperty2" }, type3: { class: "myClass3", property1: "myProperty3" } }Последний Служебный Файл
import { Injectable } from '@angular/core'; declare var require: any; @Injectable() export class TypeService { constructor(){ this.init() }; types: any; init: Function = () => { // Get all of the types of branding available in the types folder this.types = (context => { // Get the keys from the context returned by require let keys = context.keys(); // Get the values from the context using the keys let values = keys.map(context); // Reduce the keys array to create the types object return keys.reduce( (types, key, i) => { // Update the key name by removing "./" from the begining and ".json" from the end. key = key.replace(/^\.\/([^\.]+)\.json/, (a, b)=> { return b; }); // Set the object to the types array using the new key and the value at the current index types[key] = values[i].data; // Return the new types array return types; }, {} ); })(require.context('../types', true, /.json/)); } }
Вы можете напрямую обращаться к переменным в службах из их объекта, определенного в конструкторе.
... Итак, скажем, ваш конструктор загружает службу следующим образом
constructor(private someService:SomeService){}Вы можете просто сделать
Просто будьте осторожны, чтобы не сделать этого до того, как он будет загружен служебной функцией, которая его загружает. Тогда вы получите нулевое значение.someService.theJsonObject, чтобы получить к нему доступ.
Вы можете назначать переменные вашим служебным файлам так же, как и в файлах компонентов.
Просто объявите их в служба
public JsonObject:any;И (самый простой способ) - позволить функции, вызвавшей ваш сервис, назначить вам объект JSON.
Итак, скажем, вы назвали службу так
this.serviceObject.function().subscribe ( resp => { this.serviceObject.JsonObject = resp; } );После того, как это сделано один раз, другие компоненты могут получить доступ к содержимому JSON, используя
someService.theJsonObject, Как обсуждалось ранее.
В вашем случае, я думаю, все, что вам нужно сделать, это встроить объект JSON в ваш код. Может быть, вы можете использовать
const. Это неплохой код или что-то в этом роде.
Comments