www.91084.com

GVKun编程网logo

如何使用 rxjs 有条件地缓冲?

17

本文的目的是介绍如何使用rxjs有条件地缓冲?的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于#其他系列#RxJS修炼之用弹珠测试学习RxJS、AngularJS-如何使

本文的目的是介绍如何使用 rxjs 有条件地缓冲?的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于#其他系列# RxJS修炼之 用弹珠测试学习RxJS、AngularJS-如何使用ng-repeat构建自定义过滤器以有条件地返回项目、AngularJS-有条件地使用属性指令、c – 如何使用std :: enable_if有条件地选择一个可变的构造函数?的知识。

本文目录一览:

如何使用 rxjs 有条件地缓冲?

如何使用 rxjs 有条件地缓冲?

根据条件,需要立即打印每个组的第一个成员:

this.subject
  .pipe(
    groupBy(number => number % 2 === 0),mergeMap(group => {
        return merge(              
          group.pipe(first()),group.pipe(bufferTime(5000))
        )       
      })
  ).subscribe(console.log)
,

我遇到的问题是……我最初如何发送第一封电子邮件,然后在 5 分钟内收集其他所有内容?

我认为像这样修改 bufferTime 会使其工作:

/* ... */
mergeMap(group => group.pipe(
  buffer(
    concat(group.pipe(take(1)),interval(5000))
  )
)),/* ... */

这种方法是可行的,因为上面的 group 变量实际上是一个 Subject instance。

那么,ensured 组发出的值将首先存储在缓冲区中,然后释放

// buffer.ts

// first subscribing to the source (in this case,the Subject instance)
source.subscribe(new OperatorSubscriber(subscriber,(value) => currentBuffer.push(value)));

// subscribing to `buffer`'s argument
closingNotifier.subscribe(/* ... */)

#其他系列# RxJS修炼之 用弹珠测试学习RxJS

#其他系列# RxJS修炼之 用弹珠测试学习RxJS

罗里吧嗦的一些解释

RxJS使用的越来越多,但发现很多开发者都是使用最基础的部分用来处理http请求,其实RxJS可以做的事情不仅仅是在对网络资源处理过程中替代Promise,但如果按照一些已有的网络博客和分享来看,对二者在实践上的差异确实体现的不明显,所以想从测试的角度,和大家一起理解RxJS,发现它更大的威力。

另外其实本人实际上是在网络上自己学习过一些RxJS的基本概念和使用,并在项目上小小尝试过RxJS,只是觉得尝试的不够彻底,建议看这篇文章的时候最好还是对RxJS的基本概念有一个大的了解。

此文作为对RxJS有了大概了解后,从另一个观察角度去了解RxJS的一个分享。

测试,什么样的测试?

接触过测试的人可能马上会想知道,你说的是什么测试?在测试金字塔的哪一层?可以TDD吗?和我们之前了解的测试有什么特别不一样的?

我说的测试叫弹珠测试(Marble Tests),它属于底层的单元测试级别,主要用于针对自定义操作符的测试,可以TDD,比较特别的算是它是基于DSL的,你必须了解它的DSL之后才能开始写测试。

关于如何写弹珠测试,在官方github上面也有一些文档可以参考,但不是特别详细,没法像一个框架的quick start帮助大家起步。我会尝试和大家一起动手来写这些测试(从最基本的环境搭建开始),不会步步到位,但是关键步骤都有。

看第一个测试?

以下是官网随便找的一个测试,一个简单的map你可以记住你看完这个测试的感受。

  asDiagram(''map(x => 10 * x)'')(''should map multiple values'', function () {
        var a = cold(''--1--2--3--|'');
        var asubs = ''^          !'';
        var expected = ''--x--y--z--|'';
        var r = a.map(function (x) { return 10 * x; });
        expectObservable(r).toBe(expected, { x: 10, y: 20, z: 30 });
        expectSubscriptions(a.subscriptions).toBe(asubs);
    });

我并不知道你的感受,我第一眼是有点懵的反正,原因也很简单为什么出现 | ^ - 这些字符,它们在这里是干什么的? 这个时候要放出DSL这个大招了。

学弹珠测试的DSL

前面我们随意找的一个测试,似乎并不符合测试语义化这一点,其实是因为我们没有理解它所使用的DSL,此处的DSL可以理解为编写弹珠测试的时候使用的一种特定的语言,是基于弹珠测试的上下文可以让机器懂得你语义的一种语言。

我们需要简单介绍下弹珠测试所使用的DSL中的一些基本知识(此部分信息摘自cn.rx.js.org)

首先弹珠语法是用字符串表示随“时间”流逝而发生的事件。任何弹珠字符串的首字符永远都表示“零帧”。“帧”是有点类似于虚拟毫秒的概念。

基本的弹珠语法

  • "-" 时间: 10“帧”的时间段。
  • "|" 完成: 表示 Observalbe 成功完成。这是 Observable 生产者所发出的 complete() 信号。
  • "#" 错误: 终止 Observable 的错误。 这是 Observable 生产者所发出的 error() 信号。
  • "a" 任意字符: 所有其他字符表示由 Observalbe 生产者所发出的 next() 信号的值。
  • "()" 同步分组: 当多个事件需要在同一帧中同步地发出,用圆括号来将这些事件聚集在一起。你可以以这种形式来聚合值、完成或错误。 起始 ( 的位置决定了值发出的时间。
  • "^" 订阅时间点: (只适用于热的 Observabe) 显示测试 Observable 订阅热的 Observable 的点。它是此 Observable 的“零帧”,在 ^ 前的所有帧都将是无效的。

Subscription 的弹珠语法

  • "-" 时间: 10“帧”的时间段。
  • "^" 订阅时间点: 显示订阅发生的时间点。
  • "!" 取消订阅时间点: 显示取消订阅发生的时间点。

所以我们尝试逐行理解下前面出现的测试

  asDiagram(''map(x => 10 * x)'')(''should map multiple values'', function () {
       ***
    });

asDiagram是指基于测试生成 PNG 弹珠图,生成弹珠图的原理是根据一些结构化的信息,加上一些如imagemagick的库,就可以生成如下的图了,更多的操作符对应的弹珠图例子可以再rxmarbles.com找到。
图片描述

 var a = cold(''--1--2--3--|'');
 var asubs = ''^          !'';
 var expected = ''--x--y--z--|'';
 var r = a.map(function (x) { return 10 * x; });
 expectObservable(r).toBe(expected, { x: 10, y: 20, z: 30 });
 expectSubscriptions(a.subscriptions).toBe(asubs);

这个测试的步骤是这样的

  • 创建一个 Observable a,a在第30帧传入1,第60帧传入2,第90帧传入3,第120帧complete。
  • 对a进行map操作的方法r,r将a中的每个值变为原来的10倍
  • 期待对a的进行方法r的操作后,在第30帧收到10,第60帧收到20,第90帧收到30,第120帧结束
  • 期待对a的订阅在第10帧开始,在第120帧结束

自己搭建环境?

刚刚是我们用官网的例子结合一些辅助网站的资料,对弹珠测试进行的简单的了解,下面我们开始自己搭建一个可以自己写弹珠测试、运行测试的环境。

我们先使用和官网一样的第三方依赖创建环境,等我们慢慢熟悉这套之后,再换用其他第三方的依赖搭建环境。
ready go!

首先我们创建一个ts项目(最近ts写多了),并使用yarn安装基本的测试依赖。

  "dependencies": {
    "@types/chai": "^4.0.10",
    "@types/mocha": "^2.2.45",
    "chai": "^4.1.2",
    "mocha": "^4.0.1",
    "rxjs": "^5.5.6",
    "ts-node": "^4.1.0",
    "typescript": "^2.6.2"
  },
  "scripts": {
    "test": "TS_NODE_FAST=true mocha --compilers ts:ts-node/register --opts spec/support/coverage.opts \"specs/**/*.spec.ts\""
  }

然后我依样画瓢的把对TestScheduler的包装方法copy了下,中间遇到一些写法不一样的部分稍作调整。

import { TestScheduler, Observable } from ''rxjs'';
import { SubscriptionLog } from ''rxjs/src/testing/SubscriptionLog'';
import { ColdObservable } from ''rxjs/src/testing/ColdObservable'';
import { HotObservable } from ''rxjs/src/testing/HotObservable'';
export type observableToBeFn = (marbles: string, values?: any, errorValue?: any) => void;
export type subscriptionLogsToBeFn = (marbles: string | string[]) => void;

const testScheduler =  new TestScheduler(null);
export function hot(marbles: string, values?: any, error?: any): HotObservable<any> {
  return testScheduler.createHotObservable.apply(testScheduler, arguments);
}

export function cold(marbles: string, values?: any, error?: any): ColdObservable<any> {
  return testScheduler.createColdObservable.apply(testScheduler, arguments);
}

export function expectObservable(observable: Observable<any>,
                                 unsubscriptionMarbles: string = null): ({ toBe:observableToBeFn }) {
  return testScheduler.expectObservable.apply(testScheduler, arguments);
}

export function expectSubscriptions(actualSubscriptionLogs: SubscriptionLog[]): ({ toBe: subscriptionLogsToBeFn }) {
  return testScheduler.expectSubscriptions.apply(testScheduler, arguments);
}

export function time(marbles: string): number {
  return testScheduler.createTime.apply(testScheduler, arguments);
}

这样基本的hot cold方法就可以使用啦!

图片描述

下一篇 Fancy的弹珠图

弹珠测试之所以能称之为弹珠测试,从字面意思上很容易猜测和弹珠图相关。
我们已经有一个基本的测试了,下一篇我们开始把它变成弹珠图吧。

AngularJS-如何使用ng-repeat构建自定义过滤器以有条件地返回项目

AngularJS-如何使用ng-repeat构建自定义过滤器以有条件地返回项目

我有一个ng-repeat打印列表项。我想编写一个自定义过滤器,以便仅在条件为true时才打印列表项。

我似乎结构有误,因为似乎变量没有传递给过滤器。

index.php

<div ng-show="userDetails.username">    <p>Menu</p>    <li ng-repeat="menuItem in menu | matchAccessLevel:$rootScope.userDetails.accessLevel:menuItem.minAccess | orderBy:''position'' ">        <a ng-href="/angular-app/app/{{menuItem.id}}">{{menuItem.name}}</a>    </li></div>

app.js

userApp.filter(''matchAccessLevel'', function() {    return function( item, userAccessLevel, minAccessLevel ) {        if( userAccessLevel >= minAccessLevel ) {            return item;        }    }});

答案1

小编典典

过滤器无法处理数组中的单个项目,它们会将整个数组转换为另一个数组。

userApp.filter(''matchAccessLevel'', function() {  return function( items, userAccessLevel) {    var filtered = [];    angular.forEach(items, function(item) {      if(userAccessLevel >= item.minAccess) {        filtered.push(item);      }    });    return filtered;  };});

看到这个plnkr

*始终检查函数的参数。值并不总是很明显。

请参阅过滤器指南

AngularJS-有条件地使用属性指令

AngularJS-有条件地使用属性指令

我正在使用“可拖动”指令来支持图像拖动。但是,根据用户的角色,我需要为某些用户组禁用图像拖动。我使用了以下代码。

<!--draggable attribute is used as handle to make it draggable using jquery event-->           
<li  ng-repeat="template in templates" draggable id="{{template._id}}" type="template">            
<!-- Images and other fields are child of "li" tag which can be dragged.-->                    
</li>

该方法dragSupported在模板范围内,并返回truefalse。我不想为所返回的每个值创建两个大的重复<li>元素。换句话说,我不是在寻找以下方法来解决此问题。ng- if``dragSupported()

<!--draggable attribute is used as handle to make it draggable using jquery event-->           
<li ng-if="dragSupported() ==true"  ng-repeat="template in templates" draggable id="{{template._id}}" type="template">            
<!-- Images and other fields are child of "li" tag which can be dragged.-->                    
</li>
<!--remove "draggable" directive as user doesn't have permission to drag file -->
<li ng-if="dragSupported() !=true"  ng-repeat="template in templates"  id="{{template._id}}" type="template">            
<!-- Images and other fields are child of "li" tag which can be dragged.-->                    
</li>

还有其他方法可以避免代码重复吗?

c – 如何使用std :: enable_if有条件地选择一个可变的构造函数?

c – 如何使用std :: enable_if有条件地选择一个可变的构造函数?

我试图使一个类应该继承其他类的构造函数,但不继承这些类本身.

在我的类的初始化期间,我想使用完美转发来创建一个类型的对象,其构造函数与给定的参数相匹配.

除了没有参数的默认构造函数之外,不应有歧义.

这是我的代码:

#include <string>using namespace std;//NOTE: this class is just an example to demonstrate the problemclass String {    public:        //default constructor to prevent ambiguity        String() {}        //construct from wstring        template<typename... Args>        String(enable_if<is_constructible<wstring,Args...>::value,Args>::type&&... args) : ws(forward<Args>(args)...) {}        //construct from string        template<typename... Args>        String(enable_if<is_constructible<string,Args>::type&&... args) : s(forward<Args>(args)...) {}    private:        string s;        wstring ws;};void foo(const String& string) {}int main(){    foo(L"123");    foo("123");    return 0;}

我尝试了许多事情,但我根本无法让它工作.

>在当前的方法中,enable_if无法自动扣除模板args(我认为)
>由于我使用构造函数,我不能在返回值上使用enable_if
>为enable_if添加另一个默认参数将不起作用,因为构造函数是可变的
>当我从函数参数中删除enable_if时,编译器会抱怨无效重载(当然)

有没有一个优雅的方式来解决这个问题?

编辑:
标准允许的一个隐式转换不应该发生在我的类中. [编辑示例代码]

与上述示例一起使用的一个解决方案是定义单个可变构造函数,并将参数完美转换为条件初始化函数.但是,我想避免这种开销,因为成员需要被默认构造,这在其他情况下可能不起作用.

(如果事情可以更清楚,随意编辑这个问题)

解决方法

使模板化构造函数仅适用于某些类型的标准方法是使用默认的模板参数,如下所示:
#include <type_traits>#include <utility>struct Foo{    Bar x;    template <typename ...Args,typename = std::enable_if_t<std::is_constructible<Bar,Args...>::value>>    Foo(Args &&... args)    : x(std::forward<Args>(args)...)    { }};

(这里,enable_if_t< T>是用于typename enable_if< T> :: type的别名,它是C 14中的库的一部分)

一个不同的,不相关的问题是根据参数选择不同的构造函数.这个问题可以通过引入私有,不同的重载,然后使公共构造函数发送到这些私有版本来解决(请参阅DyP的解决方案,如果你愿意,我可以详细说明).但是,您仍然需要SFINAE控制您的公共构造函数,以允许只匹配任何一个私有版本的构造函数.在你的情况下:

template <typename ...Args,typename = std::enable_if_t<              std::is_constructible<std::string,Args...>::value> ||              std::is_constructible<std::wstring,Args...>::value>>String(Args &&... args): String({},std::forward<Args>(args)...)//       ^^^{ }

现在,我们只需要为第一个私有参数组成一个任意的默认可构造类型的族:

class String{    std::string s;    std::wstring ws;    template <int> struct X {};    template <typename ...Args,typename = std::enable_if_t<                  std::is_constructible<std::string,Args...>::value>>    String(X<1>,Args &&... args) : s(std::forward<Args>(args)...),ws() { } //        ^^^^^    template <typename ...Args,typename = std::enable_if_t<                  std::is_constructible<std::wstring,Args...>::value>>    String(X<2>,Args &&... args) : s(),ws(std::forward<Args>(args)...) { } //        ^^^^^public: // as above};

今天关于如何使用 rxjs 有条件地缓冲?的讲解已经结束,谢谢您的阅读,如果想了解更多关于#其他系列# RxJS修炼之 用弹珠测试学习RxJS、AngularJS-如何使用ng-repeat构建自定义过滤器以有条件地返回项目、AngularJS-有条件地使用属性指令、c – 如何使用std :: enable_if有条件地选择一个可变的构造函数?的相关知识,请在本站搜索。

本文标签: