如果我直接订阅它,Observable.bindCallback只返回值

时间:2016-12-28 16:56:52

标签: rxjs rxjs5

如果直接订阅它,Observable.bindCallback只返回值 换句话说,这很好用:

return this.store.select(store => store.appDb.appBaseUrl)
            .take(1)
            .mergeMap(baseUrl => {
                const url = `${baseUrl}?command=GetCustomers&resellerUserName=aaa&resellerPassword=bbbb`;
                return this.http.get(url)
                    .map(res => {
                        var xmlData = res.text()
                        const boundCallback = Observable.bindCallback(this.processXml, (xmlData: any) => xmlData);
                        return boundCallback(this, xmlData)
                            .subscribe((x) => {
                                return x;
                            });
                    })
            })

然而我需要避免订阅,因为我在@effect内部运行,我自动为我订阅,所以我运行:

return this.store.select(store => store.appDb.appBaseUrl)
            .take(1)
            .mergeMap(baseUrl => {
                const url = `${baseUrl}?command=GetCustomers&resellerUserName=aaa&resellerPassword=aaa`;
                return this.http.get(url)
                    .map(res => {
                        var xmlData = res.text()
                        const boundCallback = Observable.bindCallback(this.processXml, (xmlData: any) => xmlData);
                        var d:any = boundCallback(this, xmlData)
                        return d;
                    }).map(d=>{console.log(d)})
            })

但现在我得到的是:

,而不是获得一个值

这是d:

enter image description here

问候

肖恩

2 个答案:

答案 0 :(得分:2)

如果我明白你想做什么,它应该看起来像这样(显然我没有测试它):

return this.store.select(store => store.appDb.appBaseUrl)
            .take(1)
            .mergeMap(baseUrl => {
                const url = `${baseUrl}?command=GetCustomers&resellerUserName=aaa&resellerPassword=aaa`;
                return this.http.get(url)
                    .mergeMap(res => {
                        var xmlData = res.text()
                        const boundCallback = Observable.bindCallback(this.processXml, (xmlData: any) => xmlData);
                        return boundCallback(this, xmlData)
                    }).do(d => console.log(d))
            })

我使用mergeMap()因为我想从boundCallback()返回的Observable中获取值。

使用map()时,始终需要返回值进一步传播的值。在您的示例中,您不会返回任何内容,因此您只需使用do()即可查看打印的值。

编辑:

因此,这是您尝试做的简化版本。

class A {
    private processXml(context, xmlData, cb) {
        context.parseString(xmlData, {attrkey: 'attr'}, function (err, result) {
            if (err || !result) return cb(null); return cb(result);
        })
    }

    private parseString(str, _, cb) {
        return cb(null, str);
    }

    private mockHttpGet() {
        return Rx.Observable.of({
            text: () => {
                return 'abc';
            }
        });
    }

    test() {
        return this.mockHttpGet()
            .mergeMap(res => {
                var xmlData = res.text();
                const boundCallback = Rx.Observable.bindCallback(this.processXml, (xmlData: any) => xmlData);
                return boundCallback(this, xmlData)
            }).do(d => console.log(d))
    }
}

let a = new A();
a.test().subscribe(val => console.log('subscribed result', val));

查看现场演示:https://jsbin.com/reweraw/2/edit?js,console

此演示打印:

abc
subscribe abc

BoundCallbackObservable(这也适用于运营商)在您订阅它们之前不做任何事情。这就是为什么在调试器中你只看到原始数据。

我的演示工作正如您所希望的那样,请查看我如何使用mergeMap()从嵌套的Observable中获取实际值,并尝试在您的应用程序中复制相同的逻辑。

答案 1 :(得分:0)

找到了解决方案,我是一个Obs太深了:

return this.store.select(store => store.appDb.appBaseUrl)
            .take(1)
            .mergeMap(baseUrl => {
                const url = `${baseUrl}?command=GetCustomers&resellerUserName=reseller@ms.com&resellerPassword=XXXX`;
                return this.http.get(url)
                    .map(res => {
                        return res.text()
                    }).flatMap(jData=>{
                        const boundCallback = Observable.bindCallback(this.processXml, (xmlData: any) => xmlData);
                        return boundCallback(this, jData)
                    }).map(businessData=>{
                        return businessData;
                    })
            })