本文的目的是介绍如何使用rxjs有条件地缓冲?的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于#其他系列#RxJS修炼之用弹珠测试学习RxJS、AngularJS-如何使
本文的目的是介绍如何使用 rxjs 有条件地缓冲?的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于#其他系列# RxJS修炼之 用弹珠测试学习RxJS、AngularJS-如何使用ng-repeat构建自定义过滤器以有条件地返回项目、AngularJS-有条件地使用属性指令、c – 如何使用std :: enable_if有条件地选择一个可变的构造函数?的知识。
本文目录一览:- 如何使用 rxjs 有条件地缓冲?
- #其他系列# RxJS修炼之 用弹珠测试学习RxJS
- AngularJS-如何使用ng-repeat构建自定义过滤器以有条件地返回项目
- AngularJS-有条件地使用属性指令
- c – 如何使用std :: enable_if有条件地选择一个可变的构造函数?
如何使用 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使用的越来越多,但发现很多开发者都是使用最基础的部分用来处理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构建自定义过滤器以有条件地返回项目
我有一个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-有条件地使用属性指令
我正在使用“可拖动”指令来支持图像拖动。但是,根据用户的角色,我需要为某些用户组禁用图像拖动。我使用了以下代码。
<!--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
在模板范围内,并返回true
或false
。我不想为所返回的每个值创建两个大的重复<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有条件地选择一个可变的构造函数?
在我的类的初始化期间,我想使用完美转发来创建一个类型的对象,其构造函数与给定的参数相匹配.
除了没有参数的默认构造函数之外,不应有歧义.
这是我的代码:
#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有条件地选择一个可变的构造函数?的相关知识,请在本站搜索。
本文标签: