【问题标题】:Can forkJoin be used to overwrite the values in one Observable with the values of another?可以使用 forkJoin 用另一个 Observable 的值覆盖一个 Observable 中的值吗?
【发布时间】:2018-01-09 14:57:49
【问题描述】:

我是 Angular 2 的新手,我希望我能解释清楚。我有 3 个 http 路径 - 1、2 和 3。我想合并/覆盖这些。我希望 path3 成为我的默认值。

如果 path2 中存在一个值,我希望该值覆盖 path3 中的该值,并且与 path1 相同。因此,path1 中的值是最重要的,但如果 path1 中的值为 null,则应使用 path2 中的值,然后使用 path3。我试过使用forkJoin 没有成功。

如果 path1 或 path2 中的值不存在,则会显示路径名而不是分配的值。这就是我所拥有的:

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

【问题讨论】:

  • 你试过.merge吗?
  • forkjoin 将运行所有三个 http 请求,只有当所有三个请求都完成后,它才会执行 subscribe 函数。但是,在您的情况下,您似乎希望以某种顺序执行调用。 flatMap 或许能帮到你。见stackoverflow.com/questions/34523338/…

标签: angular http rxjs observable fork-join


【解决方案1】:

我创建了一个示例 jsbin .. 它按预期工作...请查看并分享您的反馈。您也可以使用它来复制您的问题。

    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。我非常感谢您花时间展示示例。不幸的是,这并没有解决问题。我发现调用没有深入到返回所需的字符串值。您的解决方案是正确的,但我没有完全解释我的问题。对不起。这是通过使用“mergeDeep”解决的。我将显示我很快使用的代码,以防其他人遇到同样的问题。
【解决方案2】:

这对我有用。这可能是因为路径名很长。

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]);

        });
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多