0

I am new to Angular 2 and I hope that I am explaining this ok. I have 3 http paths - 1, 2 & 3. I want to merge/overwrite these. I want path3 to be my default.

If there is a value present in path2, I want this value to overwrite that value in path3 and the same with path1. So, the values in path1 are the most important but if a value is null in path1, the value in path2 then path3 should be used. I have tried using forkJoin without success.

If a value in path1 or path2 is not present, the pathname rather than the assigned value is being displayed. This is what I have:

export class Loader1 implements Loader2 {
    constructor(private http: HttpClient) {
    }
    public getMethod(lang: string): any {
        return Observable.forkjoin(
            this.http.get(path1 + '.json').map((res) => res)
                .catch((res) => Observable.of(null)),
            this.http.get(path2 + '.json').map((res) => res),
            this.http.get(path3 + '.json').map((res) => res)
        ).map(results => {
            let emptyCheck = this.http.get(path1 + '.json');
            if (emptyCheck.catch((res) => Observable.of(null))) {
                results[0] = results[1];
            } else {
                emptyCheck.map((res) => res);
            }
            let result = Object.assign({}, results[2], results[1], results[0]);
            return result;
        });
    }
}

path1:
{
        "value1": "First number1",
        "value5": "First number5",
        "value10": "First number10"
}

path2:
{
        "value1": "Second number1",
        "value2": "Second number2",
        "value4": "Second number4",
        "value5": "Second number5",
        "value6": "Second number6",
        "value7": "Second number7",
        "value10": "Second number10"
}

path3:
{
        "value1": "Third number1",
        "value2": "Third number2",
        "value3": "Third number3",
        "value4": "Third number4",
        "value5": "Third number5",
        "value6": "Third number6",
        "value7": "Third number7",
        "value8": "Third number8",
        "value9": "Third number9",
        "value10": "Third number10"
}

Expected Output:
        First number1
        Second number2
        Third number3
        Second number4
        First number5
        Second number6
        Second number7
        Third number8
        Third number9
        First number10

Actual output:
        path1.value1
        path2.value2
        Third number3
        path2.value4
        path1.value5
        path2.value6
        path2.value7
        Third number8
        Third number9
        path1.value10
msanford
  • 11,803
  • 11
  • 66
  • 93
Marty
  • 1
  • 1
  • Have you tried .merge? – Iancovici Jan 09 '18 at 15:02
  • 1
    `forkjoin` will run all three http requests and only when all three are completed it will execute the `subscribe` function. However in your case it seems that you want to execute the calls in some kind of sequence. `flatMap` might be able to help you. See https://stackoverflow.com/questions/34523338/rxjs-sequence-equvalent-to-promise-then – Sonu Kapoor Jan 09 '18 at 15:05

2 Answers2

0

i created a sample jsbin .. it is working as expected ... Please take a look and share your feedback. Also you can use this to replicate your issue.

    const path1 = {
            "value1": "First number1",
            "value5": "First number5",
            "value10": "First number10"
    };

    const path2 = {
            "value1": "Second number1",
            "value2": "Second number2",
            "value4": "Second number4",
            "value5": "Second number5",
            "value6": "Second number6",
            "value7": "Second number7",
            "value10": "Second number10"
    };

    const path3 = {
            "value1": "Third number1",
            "value2": "Third number2",
            "value3": "Third number3",
            "value4": "Third number4",
            "value5": "Third number5",
            "value6": "Third number6",
            "value7": "Third number7",
            "value8": "Third number8",
            "value9": "Third number9",
            "value10": "Third number10"
    }

    const source = Rx.Observable.forkJoin(
    Rx.Observable.of(path1),
    Rx.Observable.of(path2),
    Rx.Observable.of(path3)
    ).map( result => Object.assign({}, result[2], result[1], result[0]))

    const subscription = source.subscribe(val => console.log('First',val));

    let example1 = Object.assign({}, path3, path2, path1);
    console.log('second', example1)

    let example2 = Object.assign({}, null, null, path1);
    console.log('Third', example2)

JSBIN Sample

Ashwani Kumar
  • 216
  • 2
  • 14
  • Thanks very much for your help Ashwani. I really appreciate you spending time on displaying an example. Unfortunately, this did not solve the issue. I have discovered that the calls were not digging far enough to return the string value required. Your solution was correct, but I did not explain my problem fully. Sorry. This was solved by using 'mergeDeep'. I will display the code that I used shortly in case anyone else runs into the same problem. – Marty Jan 10 '18 at 10:57
0

This is what worked for me. It is probably because there is a long path-name.

export class Loader1 implements Loader2 {
    constructor(private http: HttpClient) {
    }

    public isObject(item) {
        return (item && typeof item === 'object' && !Array.isArray(item));
    }

    public mergeDeep(target, ...sources) {
        if (!sources.length) { return target; }
        const source = sources.shift();
        if (this.isObject(target) && this.isObject(source)) {
            for (const key in source) {
                if (this.isObject(source[key])) {
                    if (!target[key]) {
                        Object.assign(target, { [key]: {} });
                    }
                    this.mergeDeep(target[key], source[key]);
                } else {
                    Object.assign(target, { [key]: source[key] });
                }
            }
            return this.mergeDeep(target, ...sources);
        }
    }

    public getMethod(lang: string): any {
        return Observable.forkJoin(
            this.http.get(path1 + '.json').map((res) => res)
                .catch((res) => Observable.of(null)),
            this.http.get(path2 + '.json').map((res) => res),
            this.http.get(path3 + '.json').map((res) => res)
        ).map(results => {

            return this.mergeDeep({}, results[2], results[1], results[0]);

        });
    }
}
Marty
  • 1
  • 1