如何使用 Promise 等待 observable 的每个值

2023-12-21

假设我有这个可观察的:

const obs = new Observable((observer) => {
    observer.next(0.25);
    observer.next(0.75);
    observer.next(new ArrayBuffer(100));
    observer.complete();
});

我怎样才能用承诺来等待每个值?

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

const value = await obs.toPromise();

但我希望能够一路获得每个值。我可以做这样的事情:

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

这更类似于发电机。

有没有办法完成这样的事情?


看来您要求的是一种将可观察量转换为异步可迭代量的方法,以便您可以“手动”或使用新的异步迭代其值等待-等待 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of语言特征。

以下是如何执行此操作的示例(我尚未测试此代码,因此它可能存在一些错误):

// returns an asyncIterator that will iterate over the observable values
function asyncIterator(observable) {
  const queue = []; // holds observed values not yet delivered
  let complete = false;
  let error = undefined;
  const promiseCallbacks = [];

  function sendNotification() {
    // see if caller is waiting on a result
    if (promiseCallbacks.length) {
      // send them the next value if it exists
      if (queue.length) {
        const value = queue.shift();
        promiseCallbacks.shift()[0]({ value, done: false });
      }
      // tell them the iteration is complete
      else if (complete) {
        while (promiseCallbacks.length) {
          promiseCallbacks.shift()[0]({ done: true });
        }
      }
      // send them an error
      else if (error) {
        while (promiseCallbacks.length) {
          promiseCallbacks.shift()[1](error);
        }
      }
    }
  }

  observable.subscribe(
    value => {
      queue.push(value);
      sendNotification();
    },
    err => {
      error = err;
      sendNotification();
    },
    () => {
      complete = true;
      sendNotification();
    });

  // return the iterator
  return {
    next() {
      return new Promise((resolve, reject) => {
        promiseCallbacks.push([resolve, reject]);
        sendNotification();
      });
    }
  }
}

与 for-wait-of 语言功能一起使用:

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);
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Promise 等待 observable 的每个值 的相关文章

随机推荐

  • 如何在没有延迟反模式的情况下将 jQuery $.ajax 调用转换为 Bluebird Promise

    现在我在核心文件中使用promise deferred 这使我能够在一个中心位置解决承诺 我一直在读到我可能正在使用反模式 我想了解为什么它不好 所以在我的core js文件我有这样的功能 var getMyLocation functio
  • 在测试复杂行为时,可以在单元测试中使用多个断言吗?

    这是我的具体场景 我有课QueryQueue包裹着QueryTaskArcGIS API for Flex 中的类 这使我能够轻松地将多个查询任务排队执行 呼唤QueryQueue execute 迭代队列中的所有任务并调用它们的执行方法
  • C#(表单)中漂亮的关键名称

    我有一个组合框 其中填充了Keys枚举 winforms 问题是对于没有经验的用户来说按键名称不是很清楚 例如 普通用户可能不知道 OemPipe 或 HanjaMode 的含义 那么 我该如何解决这个问题 并有一些更好的键名呢 我正在考虑
  • 错误:尝试在空上下文对象上调用方法“format”

    春季启动 v1 4 1 Java v1 8 百里香叶 v2 1 5 我认为以下代码行 td td 它的语法是我基于 S O 问题SpringBoot Thymeleaf 序数 https stackoverflow com question
  • DTD——ID属性的唯一性

    根据DTD规范 http www w3 org TR REC xml id关于 ID 属性类型 有效性约束 ID ID 类型的值必须与名称产生相匹配 名字不能 作为此类型的值在 XML 文档中出现多次 即 ID 值必须唯一标识承载它们的元素
  • 如何在 Windows 8 现代应用程序上从视频流中抓取帧?

    我正在尝试从 mp4 视频流中提取图像 查找完内容后 正确的方法似乎是使用 C 中的媒体基础并打开框架 从中读取内容 文档和示例很少 但经过一番挖掘后 似乎有些人已经成功地做到了这一点 通过将帧读入纹理并将该纹理的内容复制到内存可读的纹理
  • ActionMode 回调不起作用

    我正在执行一项任务 我想在文本选择上创建自定义工具提示 意味着我想在工具提示菜单中添加我自己的选项 我使用了下面的代码 它在某些设备中正常工作 如图所示 在菜单 xml中 menu menu
  • 如何在倒计时后删除 Django 对象?

    在我正在开发的平台中 我们希望用户能够为他们创建的对象设置到期时间 在他们设置的倒计时到期后 该对象应该被删除 您建议如何这样做 编辑 我应该澄清的是 每个对象的到期时间都会有所不同 执行您所描述的操作的最常见方法是创建一个列来存储创建时间
  • 为什么这个 Boost ASIO 代码不能与这个 python 客户端一起工作?

    此代码与原始 udp 异步回显服务器相同 但具有不同的套接字 响应已传输并显示在wireshark 中 但随后会向服务器发送回ICMP 端口不可达错误 我试图理解为什么 因为一切看起来都是正确的 您可以将此代码直接复制到源文件中 例如服务器
  • 如何更改 group_vars 和 host_vars 的路径?

    我们可以通过修改来改变角色的路径roles path in ansible cfg 但该文档似乎没有提及任何有关更改路径的内容group vars and host vars 我怎样才能改变这些路径 我将把与ansible相关的文件与rai
  • 在可移动和不可复制的类上使用移动和交换习惯是否有意义

    如果我有这样的课程 class Foo public Foo Foo Foo rhs operator Foo rhs swap this rhs void swap Foo rhs private Foo const Foo snip s
  • Dropbox oauth 窗口无法正常工作

    我正在将我的应用程序移植到 Electron 我惊讶地发现 Dropbox 身份验证在此环境中不起作用 不过它在 Chrome 中确实有效 登录按钮保持禁用状态 并且标签出现在输入上方 控制台中显示以下消息 Content Security
  • 尝试将应用程序提交到应用程序商店时 Xcode 崩溃[重复]

    这个问题在这里已经有答案了 我正在尝试提交一个应用程序 我将其存档 然后尝试提交它 结果崩溃了 我查找了此问题的潜在解决方案 他们说只需转到首选项 gt 帐户 gt 并更新以确保您已同意所有新条款 所以我这样做并再次尝试 现在它仍然崩溃 我
  • Ruby:一类的子类之后的[数字]的语法名称[重复]

    这个问题在这里已经有答案了 我正在通过示例学习 Ruby on Rails 我在迁移文件夹中看到这里是一个示例代码 class RemoveOrderListNumberAndStateFromOrderLists lt ActiveRec
  • 渲染许多连接的四开文档

    我一直在尝试新的quarto https quarto org Rstudio 的工具 似乎我无法做旧版本中可以做的事情R笔记本 or R Markdown备择方案 我想通过几个四开文档 qmd 组织我的工作流程 并且我想生成 html 文
  • 调用 twig 扩展时出现未知函数错误

    我正在寻找创建一个 twig 扩展 但 Symfony 一直告诉我我的功能未知 这是我的课程
  • Managed Oracle ODP.NET 驱动程序是否使用网络加密?

    我最近读到 Oracle 支持 Oracle 客户端和服务器之间的网络加密 我假设 如果服务器支持此功能 客户端就可以在各种 Oracle 数据访问提供程序库使用的完整 Oracle 客户端驱动程序中完成连接 但是 我的应用程序使用来自 O
  • 如何在 SQL Server 中存储和检索 varbinary(max) 列

    我正在开发一个应用程序 我想将用户的指纹存储到数据库中 然后将其与从设备中获取的指纹进行比较 我在转换时遇到了某些问题varbinary max 列返回一个字节 我尝试过使用GetSqlBinary功能但它给了我indexoutofrang
  • 自动选择 WPF TextBox 中焦点上的所有文本

    如何自动选择 WPF 文本框中焦点上的所有文本 乔纳森 通过向应用程序添加全局事件处理程序 您可以非常轻松地做到这一点 http madprops org blog wpf textbox selectall on focus http m
  • 如何使用 Promise 等待 observable 的每个值

    假设我有这个可观察的 const obs new Observable observer gt observer next 0 25 observer next 0 75 observer next new ArrayBuffer 100