Observable.bindCallback 如果我直接订阅它只有 returns 值

Observable.bindCallback only returns value if I subscribe to it directly

Observable.bindCallback如果我直接订阅的话只有returns值 换句话说,这很好用:

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:

问候

肖恩

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

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() 因为我想从 return 由 boundCallback() 编辑的 Observable 中获取值。

此外,在使用 map() 时,您 始终需要 return 一个可以进一步传播的值 。在您的示例中,您没有 returning 任何东西,因此您可以仅使用 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 获取实际值并尝试在您的应用程序中复制相同的逻辑。

找到解决办法了,我是一个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;
                    })
            })