简体   繁体   English

从共享服务angular2获取数据

[英]Getting data from a shared service angular2

What I want to achieve is: uploading an image from the first component using the uploaderService. 我要实现的是:使用uploaderService从第一个组件上传图像。 After successful uploading, my server is sending a key as HTTP response which I am being able to access/print from the first component. 成功上传后,我的服务器正在发送一个密钥作为HTTP响应,我可以从第一个组件进行访问/打印。 After successful uploading, the first componet is redirecting to second component. 成功上传后,第一个组件将重定向到第二个组件。 Now, I want to access/print/use the value of the key from the service (that's already accessible to the first component) in the second component. 现在,我想从第二个组件中的服务(第一个组件已经可以访问)访问/打印/使用键的值。

What I tried is: Making the service a shared service which is Injectable. 我尝试的是:使服务成为可注入的共享服务。 So if I import the service and initiate it with a constructor it should have the same instance of the service the first component is using. 因此,如果我导入服务并使用构造函数启动它,则它应该具有第一个组件正在使用的相同服务实例。 So the value I am getting in the success callback in the first component should be accessible to my second component somehow. 因此,我在第二个组件中应该可以以某种方式访问​​在第一个组件中的成功回调中获取的值。 Here are my codes. 这是我的代码。

nb: I have provided the service to the ngModule. nb:我已经为ngModule提供了服务。 I guess it's now shared enough, and fully accessible from both of my components. 我想它现在已经足够共享了,并且可以从我的两个组件中完全访问。 I am successfully using the service and getting the key in the first component. 我已成功使用该服务,并在第一个组件中获取了密钥。 But not sure how to get it in the second component. 但不确定如何在第二部分中获取它。 The fat arrow functions are confusing me. 粗箭头功能使我感到困惑。 Shouldn't I be able to get the value of a variable x, from a function A in the service by calling it in the component like: 我不应该通过在组件中调用它来从服务中的函数A获取变量x的值:

someassignablevariable = this.service.x; someassignablevariable = this.service.x;

My First Component: 我的第一个组件:

import {Component, Output} from '@angular/core';
import { Uploader } from '../services/uploader';
import { MyUploadItem } from '../services/my-upload-item';
import {Router} from "@angular/router";

@Component({
    template: `
//tempate codes
    `
})

export class FirstComponent {
    constructor(public uploaderService: Uploader, private _router: Router) { }

    public pushKey: String;

    submit() {
        let uploadFile = (<HTMLInputElement>window.document.getElementById('sampleFile')).files[0];


        let myUploadItem = new MyUploadItem(uploadFile);

        this.uploaderService.onSuccessUpload = (item, response, status, headers) => {
            // success callback
            this.pushKey = response.toString();
            console.log('Push Key:'+ response.toString())
            this._router.navigate(['second-component']);
        };
        this.uploaderService.onErrorUpload = (item, response, status, headers) => {
            // error callback

            console.log(response.toString());
        };
        this.uploaderService.onCompleteUpload = (item, response, status, headers) => {
            // complete callback, called regardless of success or failure
            console.log(response.toString());
        };
        this.uploaderService.onProgressUpload = (item, percentComplete) => {
            // progress callback
            console.log(percentComplete);
        };
        this.uploaderService.upload(myUploadItem);
    }
}

My Second Component: 我的第二部分:

import {Component, OnInit} from '@angular/core';
import {Uploader} from "../services/uploader";

@Component({
    template: `
    ....
    <p>Push Key: {{pushKey}}</p>               
    ....
    `
})


export class SecondComponent{

    constructor(public uploaderService: Uploader) { }

    pushKey: String;

    ngOnInit(){this.getKey()}

        getKey() {

            this.uploaderService.onSuccessUpload = (item, response, status, headers) => {
                // success callback
                this.pushKey = response.toString();
                console.log('Push Key:' + this.pushKey);
            };
            return this.pushKey;
        }
}

My Service: 我的服务:

import { Injectable }  from '@angular/core';
import { UploadItem }  from './upload-item';

@Injectable()
export class Uploader {
    onProgressUpload = (item: UploadItem, progress: number) => {};
    onCompleteUpload = (item: UploadItem, response: any, status: any, headers: any) => {};
    onSuccessUpload = (item: UploadItem, response: any, status: any, headers: any) => {};
    onErrorUpload = (item: UploadItem, response: any, status: any, headers: any) => {};
    onCancelUpload = (item: UploadItem, response: any, status: any, headers: any) => {};

    constructor() { }

    upload(item: UploadItem) {
        if(this.isHTML5()) {
            this.xhrTransport(item);
        } else {
            this.onErrorUpload(item, 'Unsupported browser.', null, null);
        }
    }

    private isHTML5(): boolean {
        return !!((<any>window).File && (<any>window).FormData);
    }

    private xhrTransport(item: UploadItem) {
        let xhr  = new (<any>window).XMLHttpRequest();
        let form = new (<any>window).FormData();

        this.forEach(item.formData, (key: string, value: any) => {
            form.append(key, value);
        });

        form.append(item.alias, item.file, item.file.name);


        xhr.upload.onprogress = (event: any) => {
            let progress = Math.round(event.lengthComputable ? event.loaded * 100 / event.total : 0);
            this.onProgressUpload(item, progress);
        };

        xhr.onload = () => {
            let headers = this.parseHeaders(xhr.getAllResponseHeaders());
            let response = this.parseResponse(headers['Content-Type'], xhr.response);
            if(this.isSuccessStatus(xhr.status)) {
                this.onSuccessUpload(item, response, xhr.status, headers);
            } else {
                this.onErrorUpload(item, response, xhr.status, headers);
            }
            this.onCompleteUpload(item, response, xhr.status, headers);
        };

        xhr.onerror = () => {
            let headers = this.parseHeaders(xhr.getAllResponseHeaders());
            let response = this.parseResponse(headers['Content-Type'], xhr.response);
            this.onErrorUpload(item, response, xhr.status, headers);
            this.onCompleteUpload(item, response, xhr.status, headers);
        };

        xhr.onabort = () => {
            let headers = this.parseHeaders(xhr.getAllResponseHeaders());
            let response = this.parseResponse(headers['Content-Type'], xhr.response);
            this.onCancelUpload(item, response, xhr.status, headers);
            this.onCompleteUpload(item, response, xhr.status, headers);
        };

        xhr.open(item.method, item.url, true);

        xhr.withCredentials = item.withCredentials;

        this.forEach(item.headers, (name: string, value: string) => {
            xhr.setRequestHeader(name, value);
        });

        xhr.send(form);
    }

    private isSuccessStatus(status: number) {
        return (status >= 200 && status < 300) || status === 304;
    }

    private forEach(obj: any, callback: any) {
        for (var i in obj) {
            if (obj.hasOwnProperty(i)) {
                callback(i, obj[i]);
            }
        }
    }

    private parseHeaders(headers: string) {
        let dict = {};
        let lines = headers.split('\n');
        for (let i = 0; i < lines.length; i++) {
            let entry = lines[i].split(': ');
            if(entry.length > 1) {
                dict[entry[0]] = entry[1];
            }
        }
        return dict;
    }

    private parseResponse(contentType: string, response: string) {
        let parsed = response;
        if(contentType && contentType.indexOf('application/json') === 0) {
            try {
                parsed = JSON.parse(response);
            } catch(e) {
            }
        }
        return parsed;
    }

}

Your service will be a singleton, if you provide it in a higher level to both of your components, component 1 and component 2. Then your component 2 will see in the service what component 1 has done to it. 如果您将更高级别的服务提供给组件1和组件2这两个组件,则您的服务将是单例的。然后,组件2将在服务中看到组件1对它所做的工作。

For example: 例如:

(1) Declare a property keyForUpload in your service (1)在服务中声明属性keyForUpload

(2) Let component 1 class to update keyForUpload after successful image upload (2)成功上传图片后,让组件1类更新keyForUpload

this.uploaderService.keyForUpload=123;

(3) Now your component 2 can access the keyForUpload (3)现在您的组件2可以访问keyForUpload

keyForUpload = this.uploaderService.keyForUpload // the value will be 123

This is possible because both of your components are having a single instance of the service. 这是可能的,因为您的两个组件都具有该服务的单个实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM