Javascript 如何用承诺等待可观察到的每一个值

Javascript 如何用承诺等待可观察到的每一个值,javascript,promise,rxjs,observable,rxjs6,Javascript,Promise,Rxjs,Observable,Rxjs6,假设我有一个可观察的: const obs = new Observable((observer) => { observer.next(0.25); observer.next(0.75); observer.next(new ArrayBuffer(100)); observer.complete(); }); 我怎样才能用承诺等待每一个价值 以下代码将仅返回最后一个值(调用complete()之前的值): 但我希望能够在过程中获得每个值。我可以这样做

假设我有一个可观察的:

const obs = new Observable((observer) => {
    observer.next(0.25);
    observer.next(0.75);
    observer.next(new ArrayBuffer(100));
    observer.complete();
});
我怎样才能用承诺等待每一个价值

以下代码将仅返回最后一个值(调用complete()之前的值):

但我希望能够在过程中获得每个值。我可以这样做:

const value1 = await obs.pipe(take(1)).toPromise();
const value2 = await obs.pipe(take(2)).toPromise();
但这并不理想,因为我必须每次递增数字,而且
take(1000)
在示例中仍然会返回一些内容,即使只有3个值。我要找的东西是:

const value1 = await obs.pipe(next()).toPromise(); // 0.25
const value2 = await obs.pipe(next()).toPromise(); // 0.75
const value3 = await obs.pipe(next()).toPromise(); // ArrayBuffer(100)
const value4 = await obs.pipe(next()).toPromise(); // null
这更类似于发电机


有没有一种方法可以完成这样的事情?

这可能就行了,因为take(1)完成了可观测值,然后它被Wait消耗,接下来的一个将产生第二个发射值2

const observer= new Subject()
async function getStream(){
  const value1 = await observer.pipe(take(1)).toPromise() // 0.25
  const value2 = await observer.pipe(take(1)).toPromise() // 0.75
  return [value1,value2]
}
getStream().then(values=>{
  console.log(values)
})
//const obs = new Observable((observer) => {
 setTimeout(()=>{observer.next(0.25)},1000);
 setTimeout(()=>observer.next(0.75),2000);

更新:使用subject来发射。

这可能会起作用,因为take(1)完成了可观测值,然后它被Wait消耗,接下来的一个将产生第二个发射值2

const observer= new Subject()
async function getStream(){
  const value1 = await observer.pipe(take(1)).toPromise() // 0.25
  const value2 = await observer.pipe(take(1)).toPromise() // 0.75
  return [value1,value2]
}
getStream().then(values=>{
  console.log(values)
})
//const obs = new Observable((observer) => {
 setTimeout(()=>{observer.next(0.25)},1000);
 setTimeout(()=>observer.next(0.75),2000);

更新:使用subject来发射。

您所要求的似乎是一种将可观测值转换为异步可观测值的方法,以便您可以“手动”或使用新的语言功能异步迭代其值

下面是一个如何做到这一点的示例(我没有测试这段代码,所以它可能有一些bug):

与等待语言功能一起使用:

async someFunction() {
  const obs = ...;
  const asyncIterable = {
    [Symbol.asyncIterator]: () => asyncIterator(obs)
  };

  for await (const value of asyncIterable) {
    console.log(value);
  }
}
async someFunction() {
  const obs = ...;
  const it = asyncIterator(obs);

  while (true) {
    const { value, done } = await it.next();
    if (done) {
      break;
    }

    console.log(value);
  }
}
无需等待即可使用语言功能:

async someFunction() {
  const obs = ...;
  const asyncIterable = {
    [Symbol.asyncIterator]: () => asyncIterator(obs)
  };

  for await (const value of asyncIterable) {
    console.log(value);
  }
}
async someFunction() {
  const obs = ...;
  const it = asyncIterator(obs);

  while (true) {
    const { value, done } = await it.next();
    if (done) {
      break;
    }

    console.log(value);
  }
}

看起来您需要的是一种将可观测值转换为异步可观测值的方法,以便您可以“手动”或使用新的语言功能异步迭代其值

下面是一个如何做到这一点的示例(我没有测试这段代码,所以它可能有一些bug):

与等待语言功能一起使用:

async someFunction() {
  const obs = ...;
  const asyncIterable = {
    [Symbol.asyncIterator]: () => asyncIterator(obs)
  };

  for await (const value of asyncIterable) {
    console.log(value);
  }
}
async someFunction() {
  const obs = ...;
  const it = asyncIterator(obs);

  while (true) {
    const { value, done } = await it.next();
    if (done) {
      break;
    }

    console.log(value);
  }
}
无需等待即可使用语言功能:

async someFunction() {
  const obs = ...;
  const asyncIterable = {
    [Symbol.asyncIterator]: () => asyncIterator(obs)
  };

  for await (const value of asyncIterable) {
    console.log(value);
  }
}
async someFunction() {
  const obs = ...;
  const it = asyncIterator(obs);

  while (true) {
    const { value, done } = await it.next();
    if (done) {
      break;
    }

    console.log(value);
  }
}


为什么这需要一个承诺?@KevinB为什么不?我想用async/await.Right来构造我的代码,但是,它看起来不像你在做任何异步的事情,所以。。。理论上,无论是否等待,它都会以同样的方式工作。如果您所做的不是异步的,那么async/await将只是多余的代码,没有任何意义。这只是一个简化的示例,请想象可观察对象以异步方式发出事件。@MaximedPre有一个问题,如果有答案,您可以尝试。虽然我仍然不确定将异步与可观察对象结合使用的大想法是否有效。为什么这需要成为一个承诺?@KevinB为什么不?我想用async/await.Right来构造我的代码,但是,它看起来不像你在做任何异步的事情,所以。。。理论上,无论是否等待,它都会以同样的方式工作。如果您所做的不是异步的,那么async/await将只是多余的代码,没有任何意义。这只是一个简化的示例,请想象可观察对象以异步方式发出事件。@MaximedPre有一个问题,如果有答案,您可以尝试。尽管我仍然不确定将异步与可观察对象结合使用的想法是否有效,但这是行不通的。所有变量(value1..value4)的第一个发出值为-0.25。要使它工作,需要将每个take都更改为(take(1)…take(4))。那么就在while循环中等待它们吧?或者只是订阅一个可观察的,因为它们是要使用的。或者根本不使用可观测数据,首先使用承诺。更新答案,测试它,它会工作的。虽然我认为它没有抓住异步的要点programming@taras-d是正确的,您需要增加每个
取数
,否则您将始终使用
取数(1)
获得第一个值。我使用
主题
测试了这里提出的解决方案,但这并不是一个好的选择,因为它不会等到客户机订阅后才推送值。用户可以订阅一个主题而不接收以前推送的值,因为该过程是在客户端订阅之前启动的。由于同样的原因,ReplaySubject也不是一个好的选择,推送值的过程应该在客户端订阅可观察对象之后开始,而不是之前。那么为什么不使用generator呢?这将不起作用。所有变量(value1..value4)的第一个发出值为-0.25。要使它工作,需要将每个take都更改为(take(1)…take(4))。那么就在while循环中等待它们吧?或者只是订阅一个可观察的,因为它们是要使用的。或者根本不使用可观测数据,首先使用承诺。更新答案,测试它,它会工作的。虽然我认为它没有抓住异步的要点programming@taras-d是正确的,您需要增加每个
取数
,否则您将始终使用
取数(1)
获得第一个值。我使用
主题
测试了这里提出的解决方案,但这并不是一个好的选择,因为它不会等到客户机订阅后才推送值。用户可以订阅一个主题而不接收以前推送的值,因为该过程是在客户端订阅之前启动的。由于同样的原因,ReplaySubject也不是一个好的选择,推送值的过程应该只在客户端订阅可观察对象之后开始,而不是之前。那么为什么不使用generator而不是TeadNice呢!这很有效。您是否编写了此代码,如果没有,是否可以链接源代码?谢谢美好的这很有效。您是否编写了此代码,如果没有,是否可以链接源代码?谢谢