Javascript 将承诺转化为可观察的

Javascript 将承诺转化为可观察的,javascript,rxjs,Javascript,Rxjs,RxJS是一个非常好的库,我想将下面的函数从承诺转换为可观测 async function userGoods(userName) { let user = await userReqest(userName).toPromise(); let home = await homeReqest(user.id).toPromise(); let dog = home ? await dogReqest(user.id).toPromise() : nul

RxJS是一个非常好的库,我想将下面的函数从
承诺
转换为
可观测

    async function userGoods(userName) {
      let user = await userReqest(userName).toPromise();
      let home = await homeReqest(user.id).toPromise();
      let dog = home ? await dogReqest(user.id).toPromise() : null;

      let financeUSD = user.savings;
      if(home) financeUSD += home.price;
      if(dog) financeUSD += dog.price;

      return { 
        USD: financeUSD, 
        EUR: await usd2eurReqest(financeUSD).toPromise() 
      };
    }
Blow我创建了boiler plate working(Promises)代码段,该代码段允许轻松使用rxjs(并且可以复制来回答)。下面的代码段包含4个api请求模拟观察值(不要更改它)

//模拟的API请求可观察
设d=rxjs.operators.delay(100);
让userReqest=(name)=>rxjs.of({id:123,name:name,savings:10000}).pipe(d);
让homeReqest=(userId)=>rxjs.of({userId,颜色:“黑色”,价格:1000000});
让dogrequest=(userId)=>rxjs.of({userId,name:“Pig”,price:1000}).pipe(d);
让usd2eurReqest=(货币)=>rxjs.of(货币*1.1)管道(d);
//如何使用obserwables(无承诺)编写下面的函数?
异步函数userGoods(用户名){
let user=wait userReqest(userName).toPromise();
let home=wait homerequest(user.id).toPromise();
让dog=home?等待dogrequest(user.id).toPromise():null;
让financeUSD=user.savings;
如果(国内)财务美元+=国内价格;
如果(狗)融资美元+=狗价;
返回{
美元:财务美元,
欧元:等待2美元的货币测试(金融美元).toPromise()
};
}
// --------
//试验
// --------
//您可以将此函数更改为支持观察值,而不是等待
异步函数run(){
console.log(“johngoods”),wait userGoods(“John”);
}
run()

当您想要组合多个观测值时,您应该以rxjs的方式进行-即使用
开关映射
()。然后可以使用
Observable.toPromise()
。订阅observables是将其连接到“外部”世界(应用程序的其余部分)的一种方式

然后,您在
userGoods
中的代码将如下所示(我没有测试它,但您自己可以使用它)


使用嵌套的
switchMap
调用映射到下一个可观察对象,同时保持前一个可观察对象的值可访问。您可以将获取狗并映射到整个用户财务的代码移动到一个单独的函数,以减少一些嵌套。然后使用
swichMap
获取
EUR
,并再次使用嵌套的
map
发出两个
{USD,EUR}

const{of}=rxjs;
const{map,switchMap,delay}=rxjs.operators;
//模拟API请求可观测值
常数d=100
让userReqest=(name)=>of({id:123,name:name,savings:10000}).pipe(delay(d));
让homeReqest=(userId)=>of({userId,color:“black”,price:1000000});
让dogReqest=(userId)=>of({userId,name:“Pig”,price:1000});
让usd2eurReqest=(货币)=>of(货币*1.1).管道(延迟(d));
功能userFinance(用户,主页){
返回(home?dogrequest(user.id):of(null)).pipe(
map(dog=>user.savings+(home?home.price:0)+(dog?dog.price:0))
);
}
功能userGoods(用户名){
返回userReqest(userName).pipe(
switchMap(user=>homeReqest(user.id).pipe(
switchMap(主页=>userFinance(用户,主页))
)),
开关图(美元=>usd2eurReqest(美元)。管道(
map(欧元=>({美元,欧元}))
))
);
}
// --------
//试验
// --------
函数运行(){
用户商品(“约翰”)。订阅(
goods=>console.log(“johngoods”,goods)
);
}
运行()

在您的代码中,您没有解释如何计算财务并返回美元和欧元价值,这实际上是我最大的问题(您仍然使用承诺)。谢谢您的回答-但它看起来太复杂了,我想知道:在这种情况下,将承诺更改为可观察值真的值得吗?@KamilKiełczewski是的,在rxjs中处理顺序请求并保持前一个请求的值可访问需要嵌套,但嵌套并不总是看起来很好。我更新了我的答案,并将一些复杂度转移到一个额外的函数中,以缩短代码
const dog = userReqest(userName).pipe(
  switchMap((user) => homeRequest(user.id).pipe(
    switchMap((home) => (home ? dogRequest(user.id) : null),
  )),
).toPromise();