精华内容
下载资源
问答
  • 2020-09-24 17:47:58

    什么是响应式编程?
    如果要直接理解,可能比较抽象,但我们可以引用百度百科的例子;例如:a = b + c; 这句代码将b+c的值赋给a,而之后如果b和c的值改变了不会影响到a,然而,对于响应式编程,之后b和c的值的改变也动态影响着a,意味着a会随着b和c的变化而变化。

    响应式编程过程中,一般有以下几个组件,Observable/Operator/Subscriber;对应到代码中就是不同类。这个流程,可以简单的理解为:Observable -> Operator1 -> Operator2 -> Operator3 -> Subscriber。

    解释

    Observable:可理解为能观察的对象;例如:一个数组。

    Operator:就是对数据进行一些操作,例如:排序,过滤,两个数组合并;都是操作,同时还可以多个一起用。

    Subscriber:订阅器;目的是接收处理后的数据;在一个方法中,或者回调方法中,可以接收到操作后的数组。

    优点
    对应同步编程来说,和普通编程差不都;但对于异步编程,使用响应式会很方便。

    缺点

    代码理解起来,稍微困难一点;另外由于响应式编程学习曲线陡峭,所以很多时候不知道如何实现,或者使用了不正确方法;同时对于团队要求也高一些。

    更多相关内容
  • 响应式优点缺点??

    千次阅读 2019-06-03 19:34:28
    响应式优点缺点?? 】 大家好,我是IT修真院北京分院25期的学员,一枚正直纯洁善良的web前端程序员 今天给大家分享一下,修真院官网css任务9,深度思考中的知识点——响应式优点缺点?? ...

    这里是修真院前端小课堂,每篇分享文从

    【背景介绍】【知识剖析】【常见问题】【解决方案】【编码实战】【扩展思考】【更多讨论】【参考文献】

    八个方面深度解析前端知识/技能,本篇分享的是:

    【响应式的优点和缺点?? 】

    大家好,我是IT修真院北京分院25期的学员,一枚正直纯洁善良的web前端程序员

    今天给大家分享一下,修真院官网css任务9,深度思考中的知识点——响应式的优点和缺点??

    1.背景介绍

    随着智能手机的迅速发展,大众群体使用手机访问互联网的频率已经大大提升。

    手机的屏幕比较小,宽度通常在600像素以下;PC的屏幕宽度,一般都在1000像素以上(目前主流宽度是1366×768),有的还达到了2000像素。同样的内容,要在大小迥异的屏幕上,都呈现出满意的效果,并不是一件容易的事。

    传统的只能在pc端显示的网页,如何适应这个潮流,也成了人们开始关注和解决的问题。于是响应式布局的概念就被提出来了。

    2.知识剖析

    2.1什么是响应式

    响应式布局是Ethan Marcotte在2010年5月份提出的一个概念,简而言之,就是一个网站能够兼容多个终端——而不是为每个终端做一个特定的版本。这个概念是为解决移动互联网浏览而诞生的。响应式布局可以为不同终端的用户提供更加舒适的界面和更好的用户体验,而且随着目前大屏幕移动设备的普及,用“大势所趋”来形容也不为过。

    2.2响应式的优点

    1.响应式设计可以向用户提供友好的Web界面,同样的布局,却可以在不同的设备上有不同排版,这就是响应式最大的优点,现在技术发展日新月异,每天都会有新款智能手机推出。如果你拥有响应式Web设计,用户可以与网站一直保持联系,而这也是基本的也是响应式实现的初衷。

    2.响应式在开发维护和运营上,相对多个版本成本会降低很多。也无须花大量的时间在网站的维护上

    3.方便改动,响应式设计是针对页面的,可以只对必要的页面进行改动,其他页面不受影响。

    2.3响应式的缺点

    1.为了适配不同的设备,响应式设计需要大量专门为不同设备打造的css及js代码,这导致了文件增大,影响了页面加载速度。

     

    2.在响应式设计中,图片、视频等资源一般是统一加载的,这就导致在低分辨率的机子上,实际加载了大于它的显示要求的图片或视频,导致不必要的流量浪费,影响加载速度;

    3.局限性,响应式不适合一些大型的门户网或者电商网站,一般门户网或电商网站一个界面内容较多,对设计样式不好控制,代码过多会影响运行速度。

    3.常见问题

    如何实现响应式?

    4.解决方案

    1.流式布局

    用灵活的网格搭建一个网站布局,它可以动态的调整以适应于任何宽度。网格布局使用相对长度单位.

    这些相对长度多用于网格,诸如宽度,间距或是留白等属性。

    为了更好的控制流式布局,可以使用最小宽度(min-width),最大宽度(max-width),最小高度(min-height)和最大高度(max-height),把他们应用到容器元素(container)上。

    vw:视窗宽度;vh:视窗高度;vmin:视窗最小尺寸;vmax:视窗最大尺寸;

    2.媒体查询 MediaQuery

    自动探测屏幕宽度,然后加载相应的CSS样式,为目标设备提供有针对性的样式,在响应式设计中发挥作用。

    @media all and (min-width: 800px) and (max-width: 1024px) {...}

    在搭建响应式网站时,应该可以适应各种不同视窗尺寸,而不需要考虑设备的分辨率。设置断点只是在网站布局被破坏,看起来很怪或是内容无法显示的时候才需要设置。

    3.viewport

    meta name="viewport" content="width=device-width, initial-scale=1.0"

    width:控制 viewport 的大小,可以指定的一个值,如果 600,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)。

    initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例。

    maximum-scale:允许用户缩放到的最大比例。

    minimum-scale:允许用户缩放到的最小比例。

    user-scalable:用户是否可以手动缩放。

    4.流式媒体

    当视窗开始改变尺寸时,媒体大小并不总是做适当改变的。所以图片,视频以及其他媒体类型需要在视窗改变的情况下,按照比例改变大小。

    通过使用最大宽度值为100%,是一个快速实现媒体按照比例缩放的方法。这样做可以确保在视窗变小的情况下,任何媒体可以根据他的容器宽度,按照比例缩放。

    img, video, canvas{

    max-width: 100%;

    }

    5.编码实战

    demo1,2为响应式网站实例,demo3为响应式网站的设计

    demo1

    demo2

    demo3

    6.扩展思考

    响应式和自适应的区别是什么?

    简而言之,响应式就相当于液体,它可以自动适应不同尺寸的屏幕。响应式根据目标设备自动改变风格如显示类型,宽度、高度等,这能很好解决不同屏幕尺寸的显示问题。而自适应设计是基于断点使用静态布局,一旦页面被加载就无法再进行自动适应,自适应会自动检测屏幕的大小来加载适当的工作布局,也就是说,当你要采用自适应设计网站时,你得设计多种常见的屏幕布局。显然,自适应设计需要做更多的工作。而响应式设计可以更好地适应复杂的媒体设备要求,能很好地解决显示和性能问题。

    7.参考文献

    HTML和CSS高级指南之四——响应式设计

    响应式与自适应设计:设计师的最佳选择是什么?

    8.更多讨论

    PPT链接

    视频链接:密码: 24kt

    展开全文
  • 函数式编程优点

    千次阅读 2020-06-11 04:18:24
    在本系列的第一部分中 ,我讨论了函数式编程的核心概念,并提供了一些示例说明它们如何发挥作用。 函数编程的核心概念列表(再次从第一部分开始)如下: 使用功能作为其他功能的输入和输出, 高阶函数 使用map ...

    本系列的第一部分中 ,我讨论了函数式编程的核心概念,并提供了一些示例说明它们如何发挥作用。 函数编程的核心概念列表(再次从第一部分开始)如下:

    1. 使用功能作为其他功能的输入和输出,
      高阶函数
    2. 使用mapfilterreduce类型函数而不是循环
    3. 不变的状态
    4. 递归代替循环
    5. 从其他功能组合功能
    6. 将“纯”功能与具有副作用的功能区分开

    我给出了使用前四个项目的一些示例,因此让我们更深入地研究这些项目,并添加第5个项目。

    与Elm建立高效的国际象棋AI

    但是首先,有关国际象棋编程的一些信息:

    为类似象棋的游戏编写AI是一件很有趣的事情。 真正的国际象棋AI必须非常复杂。 与国际象棋相比,计算机下象棋的方式更为残酷。 他们尝试查看每个可能的移动顺序,并为结果位置分配一个值。 这种蛮力方法非常费力,以至于如果不进行重大优化,一台AI将需要几天的时间才能移动,并且还需要大量的内存。

    优化国际象棋AI代码的挑战已经产生了一些很棒的算法,例如alpha-beta修剪和min-max搜索。 击败世界冠军加里·卡斯帕罗夫Garry Kasparov)的AI Deep Blue内置了专门的“象棋”芯片,使其速度比纯软件解决方案快了许多倍。 另外,国际象棋公开赛百科全书包含了所有流行公开赛的最佳棋步,并且这些棋子被硬编码为国际象棋程序,因为数据不需要每部分游戏的前十到二十步都需要AI的处理。

    相比之下,我的宠物项目“伤口”的AI(请参阅本系列的第一部分 )是非常原始的。 在评估董事会中的给定职位时,它将比较军队(包括受伤的部分)的实力,并且将其各自的机动性与每个团队可以进行多少法律行动的原始计数进行比较。

    我们将看到在不耗尽某些资源(包括人的耐心)的情况下,我们可以展望未来的许多举措。

    为简单起见,我们假设每轮连续进行的合法移动次数保持不变(事实并非如此;通常随着游戏第一部分中的每次移动而增加)。 在Wounds中,第一个球员是Red球员,在游戏开始时有大约30个合法动作。 AI将尝试这些动作中的每一个作为第1层,然后它将使Blue团队的每一个响应(第2层)为30乘以30,即900。您将看到结果。 接下来将考虑Red的27,000次举动(第3页)和Blue的810,000次举动(第4页)。 当您开始寻找比这更远的时间时,很容易耗尽时间和内存。

    比较Objective-C和Elm

    当我在Objective-C中为此编写代码时,在遇到函数编程之前,我看到递归将使我能够为此编写干净的代码。 当我实现递归代码时,我发现深度为5层时,代码将使我的iPad崩溃。 造成这种情况的原因有两个:一,在董事会上进行下一步行动之前,需要保存每个董事会职位的副本;二,由于没有针对递归对Objective-C进行优化,因此会产生额外的开销。 递归调用(没有优化)会占用堆栈空间,因此通常是最弱的链接。

    让我们希望这在Elm中效果更好。 看看这个:

    makeAIMove : Player -> Board -> Board
    makeAIMove player board =
      let
        moveList = getAIMoves board player
        scoredMobility = List.map (\move -> scoreMoveMobility board player move) moveList
        scoredMoves = 
        List.map (\move -> scoreMoveMaterial board player move) scoredMobility
        sortedMoves = List.sortBy .score scoredMoves |> List.reverse 
        maybeMove = List.head sortedMoves
      in
        case maybeMove of
          Just maybeMove ->
            let _ = Debug.log "score " maybeMove.score
            in
              makeMove board maybeMove
          _ ->
            board

    在这里,我们看到对List.map的两次调用,该调用将一个函数作为输入。 如果需要,传入的函数还会获取参数。 最后,列表通过。 该函数将在列表中的每个项目上调用。 List.map将返回结果列表。 在这种情况下,我要传递动作列表。 首先是所有合法举动,然后是那些举动的得分,然后添加材料的得分,然后进行排序,以便我们可以抓住得分最高的列表的头。

    请注意,每个后续调用的结果如何放入其自己的变量中,该变量将被传递给下一个函数。 这是我的下一个尝试,其中我利用链接来消除这些临时变量:

    makeAIMove : Player -> Board -> Board
    makeAIMove player board =
      let
        maybeMove =
        getAIMoves board player
        |> List.map (\move -> scoreMoveMobility board player move)
        |> List.map (\move -> scoreMoveMaterial board player move)
        |> List.sortBy .score
        |> List.reverse
        |> List.head
      in
        case maybeMove of
          Just maybeMove ->
            makeMove board maybeMove
          _ ->
            board

    在Elm中, |>运算符将其前面的函数的输出作为最后一个参数传递给其后面的函数。 如果比较上面的代码段,您将看到在第二个代码段中,每行末尾的参数丢失了。 在语言之间,该参数传递顺序未标准化。

    例如,Elixir中的链接函数将输出参数作为第一个输入参数发送给后续函数,而不是最后一个参数。 这看起来类似于使用用于连接UNIX命令行实用程序的管道运算符。 但是可以这么说,还有一些更强大的事情正在发生。

    部分应用的功能

    当我说一个功能的输出传递给下一个功能时,我撒了点谎。 实际传递的称为部分应用函数 。 将这些信息传递出去的行为称为currying

    Currying是为了向组合逻辑的先驱Haskell Brooks Curry致敬。 动词“ to curry”不仅指他和他的作品,而且还以他的名字命名了三种函数式编程语言:Haskell,Brooks和Curry。 在这三者中,只有Haskell有大量追随者。

    像这样传递部分应用的函数是命名函数编程的另一个原因。 这个名字很贴切的另一个原因是功能程序员对所谓的副作用非常谨慎。

    在面向对象的编程中,对象包含内部状态以及它们的方法既可以读取状态又可以写入状态是司空见惯的。 代码和数据交织在一起。 如果没有精心设计,可能会出现各种难以预料的副作用。

    函数式程序员喜欢对这些副作用要非常小心。 给定相同的输入,“纯”功能始终返回相同的输出。 此外,它不会影响应用程序状态。 由于很少有没有状态的应用程序可以工作,因此需要以某种方式解决。 因此,仍然存在状态,但是必须非常谨慎和认真地处理它。

    例如,在React / Redux中,您通过编码称为“ reducers”的Redux函数来处理状态。 然后创建“动作”。 当Redux收到一个动作时,它会小心地应用任何中间件,然后调用所有的reducer。 减速器可以对自己感兴趣的动作采取行动,或者可以说只是推卸责任。 React / Redux并不是纯粹的功能性工具链,但是作者说,它们已经受到Elm架构的严重影响。

    不变状态的优雅

    让我们再次讨论不可变状态,这一次更深入地介绍了在代码中使用它的优雅之处。 “纯”功能性编程工具强制执行不可变状态。 半功能性工具(如React(与Redux)一起使用)强烈建议并假设您将坚持不变的状态设计模式。 例如ReactJS,您可以调用

    this.state = ‘new state’;

    constructor()但是应该使用后续的状态更改

    this.setState(‘new state’);

    这似乎没有被强制执行,所以我可以想象自己通过忘记此规则而引入了错误。 有点像当我键入=而不是== 。 我敢打赌,这从未发生在你身上;)。

    诸如Elixir和Elm之类的功能语言返回数据的更新副本,而不是修改数据本身。 直观地讲,这在处理和内存方面看起来都是昂贵的,但是实际上这些工具已经过优化,因此实际上效率更高而不是更低。

    这是我的(为简单起见而编辑的)Objective-C递归代码,用于搜索良好的AI动作:

    - (Move *) pickBestMove: (Board *) board forPlayer: (Player *) player depth: (int) depth
    {
        Move *bestMove = nil;
        NSMutableArray *moves = [self generateLegalMoves:board forPlayer:player];
        if(moves.count > 0)
        {
            bestMove = moves[0];
            BOOL alphaBeta = depth % 2 == 1;
            for(Move *move in moves)
            {
                move.score = 0;
                int interimValueScore = 0;
                if(move.defending_man != nil)
                {
                    interimValueScore += move.defending_man.value;
                }
                if(self.searchDepth > depth)
                {
                    if(move.defending_man != nil)
                    {
                        if(depth < 4)
                        {
                            Board *tempBoard = [board copy]; 
                            [tempBoard makeMove:move];
                            Player *nextPlayer = [self getNextPlayer:player];
                            // here's the recursive call
                            Move *nextPlyBestMove = 
                    [self pickBestMove:tempBoard forPlayer:nextPlayer 
                        depth: depth + 1];
                            if(nextPlyBestMove != nil)
                            {
                                interimValueScore += nextPlyBestMove.score;
                            }
                            [tempBoard unMakeMove:move];
                        }
                    }
                }
                if(alphaBeta)
                {
                    move.score += interimValueScore;
                    if(move.score > bestMove.score)
                    {
                        bestMove = move;
                    }
                }
                else
                {
                    move.score -= interimValueScore;
                    if(move.score < bestMove.score)
                    {
                        bestMove = move;
                    }
                }
            }
        }
        return bestMove;
    }

    每次我搜索一个更深的层(层)时,都会制作一个新的木板副本,然后在该木板的副本上进行每次移动,并为得到的位置打分。 该代码很难调试,需要各种仪器代码才能在特定深度和板上位置停止。 即使在我的iMac上,它的速度也非常慢,这意味着它无法玩出非常出色的游戏。

    现在让我们回到Elm,这要求状态是不可变的。 我在Elm制作的makeAIMove第一个版本在为移动性评分时向前看了一个动作,而在给材质评分时没有任何动作。 这非常快,但是不太聪明。 它打得非常激进,没有考虑对手的反应。 这是一个更智能的版本,它使用递归来搜索由输入参数控制的深度:

    makeAIMove : Player -> Int -> Board -> Board
    makeAIMove player searchDepth board =
      let
        maybeMove = pickBestMove player 1 4 board
      in
        case maybeMove of
          Just maybeMove ->
            maybeMove
           |> makeMove board
          _ ->
            board

    pickBestMove函数对其进行递归调用,直到达到由limit参数指定的搜索深度为止:

    pickBestMove : Player -> Int -> Int -> Board -> Maybe Move
    pickBestMove player depth limit board =
      let
        legalMoves = getAIMoves board player
        alphaBeta = (rem depth 2) /= 1
    
        setMoveScore move player depth limit board =
          if depth < limit then
            let
              nextBoard = makeMove board move
              nextPlayer = (Player.getNextPlayer player)
              -- here's the recursive call
              nextPlyBestMove =
                pickBestMove nextPlayer (depth + 1) limit nextBoard
            in
              case nextPlyBestMove of
                Just nextPlyBestMove ->
                  if alphaBeta then
                    {move | score = move.score + (scoreBoard nextPlayer nextBoard)}
                  else
                    {move | score = move.score - (scoreBoard nextPlayer nextBoard)}
                _ ->
                  move
          else
            {move | score = makeMove board move |> scoreBoard player}
      in
        List.map (\move -> setMoveScore move player depth limit board) legalMoves
        |> List.sortBy .score
        |> List.reverse
        |> List.head

    在顶部的let部分中,我定义了一个本地函数setMoveScore ,该函数setMoveScore legalMoves列表中的每个移动而legalMovessetMoveScore递归调用外部函数pickBestMove 。 本地/内部函数递归调用外部函数是一种有趣的模式。 可以将setMoveScore视为代码块而不是谨慎的功能。

    模式{move | score = makeMove board move |> scoreBoard player} {move | score = makeMove board move |> scoreBoard player}显示了Elm如何响应状态变化。 此摘要返回更新了分数的新的move副本。 这与List.map函数调用非常匹配, List.map通过将函数应用于旧列表中的每个项目来创建新列表。

    同样,函数调用nextBoard = makeMove board move返回位置更改的新板。 Player.getPlayer工作方式相同。 这非常有用,因为我们希望能够在此功能的最后一行中使用原始的boardplayer

    我们不需要在每个层深度管理这些临时板,并确保我们撤消所做的移动。 这就是Objective-C示例的工作方式。 那在很大程度上取决于可变状态。

    不变状态版本不易出错。 最终,它也变得更容易理解。 刚开始围绕FP概念进行研究时,我发现比面向对象的代码更难理解。 现在,我变得更加熟练了,我看到了这里的吸引力:一种令人上瘾的品质,对问题的正确解决方案具有优雅的感觉。 在那一刻,一切都点击了。

    接下来

    本系列的下一篇文章将深入研究React和Redux。

    翻译自: https://www.javacodegeeks.com/2017/10/advantages-functional-programming.html

    展开全文
  • JetLinks物联网基础平台-响应式

    千次阅读 多人点赞 2020-04-01 09:41:07
    JetLinks使用reactor作为响应式编程框架,从网络层(webflux,vert.x)到持久层(r2dbc,elastic)全部 封装为非阻塞,响应式调用. 响应式可以理解为观察者模式,通过订阅和发布数据流中的数据对数据进行处理. reactor提供了...

    响应式

    JetLinks使用reactor作为响应式编程框架,从网络层(webflux,vert.x)到持久层(r2dbc,elastic)全部
    封装为非阻塞,响应式调用.

    响应式可以理解为观察者模式,通过订阅发布数据流中的数据对数据进行处理.
    reactor提供了强大的API,简化了对数据各种处理方式的复杂度,如果你已经大量使用了java8 stream api,使用reactor将很容易上手.

    TIP注意:响应式传统编程最大的区别是:
    响应式中的方法调用是在构造一个流以及处理流中数据的逻辑,当中产生了数据(发布,订阅),才会执行构造好的逻辑.
    传统编程则是直接执行逻辑获取结果.

    优点

    非阻塞,集成netty等框架可实现更高的网络并发处理能力.
    API丰富,实现很多复杂的功能只需要几行代码,例如:

    1. 前端展示实时数据处理进度.
    2. 请求撤销,可获取到连接断开事件.
    3. 定时(interval),延迟(delay),超时(timout),以及细粒度的流量控制(limitRate).

    缺点

    调试不易,异常栈难跟踪,对开发人员有更高的要求.

    warning 注意:响应式只是一个编程模型,并不能直接提高系统的并发处理能力.
    通常与netty(reactor-netty)等框架配合,从上(网络)到下(持久化)全套实现非阻塞,响应式才有意义.

    说明

    系统中大量使用到了reactor,其核心类只有2个Flux(0-n个数据的流),Mono(0-1个数据的流).
    摒弃传统编程的思想,熟悉Flux,MonoAPI,就可以很好的使用响应式编程了.

    常用API:

    1. map: 转换流中的元素: flux.map(UserEntity::getId)
    2. flatMap: 转换流中的元素为新的流: flux.flatMap(this::findById)
    3. flatMapMany: 转换Mono中的元素为Flux(1转多): mono.flatMapMany(this::findChildren)
    4. concat: 将多个流连接在一起组成一个流(按顺序订阅) : Flux.concat(header,body)
    5. merge: 将多个流合并在一起,同时订阅流: Flux.merge(save(info),saveDetail(detail))
    6. zip: 压缩多个流中的元素: Mono.zip(getData(id),getDetail(id),UserInfo::of)
    7. then: 流完成后执行.
    8. doOnNext: 流中产生数据时执行.
    9. doOnError: 发送错误时执行.
    10. doOnCancel: 流被取消时执行.
    11. onErrorContinue: 流发生错误时,继续处理数据而不是终止整个流.
    12. defaultIfEmpty: 当流为空时,使用默认值.
    13. switchIfEmpty: 当流为空时,切换为另外一个流.
    14. as: 将流作为参数,转为另外一个结果:flux.as(this::save)

    完整文档请查看官方文档

    注意

    代码格式化

    使用reactor时,应该注意代码尽量以.换行并做好相应到缩进.例如:

    
    //错误
    return paramMono.map(param->param.getString("id")).flatMap(this::findById);
    
    //建议
    return paramMono
                .map(param->param.getString("id")) 
                .flatMap(this::findById);
    
    

    lamdba

    避免在一个lambda中编写大量的逻辑代码,推荐参考领域模型,将具体当逻辑放到对应到实体或者领域对象中.例如:

    
    //错误
    return devicePropertyMono
            .map(prop->{
                Map<String,Object> map = new HashMap<>();
                map.put("property",prop.getProperty());
                ....
                return map;
            })
            .flatMap(this::doSomeThing)
    
    //建议
    //在DeviceProperty中编写toMap方法实现上面lambda中到逻辑.
    return devicePropertyMono
            .map(DeviceProperty::toMap)
            .flatMap(this::doSomeThing)
    
    

    null处理

    数据流中到元素不允许为null,因此在进行数据转换到时候要注意null处理.例如:

    
    //存在缺陷
    return this.findById(id)
                .map(UserEntity::getDescription); //getDescription可能返回null,为null时会抛出空指针,
    
    

    非阻塞与阻塞

    默认情况下,reactor的调度器由数据的生产者(Publisher)决定,在WebFlux中则是netty的工作线程,
    为了防止工作线程被阻塞导致服务崩溃,在一个请求的流中,禁止执行存在阻塞(如执行JDBC)可能的操作的,如果无法避免阻塞操作,应该指定调度器如:

    paramMono
      .publishOn(Schedulers.elastic()) //指定调度器去执行下面的操作
      .map(param-> jdbcService.select(param))
    

    上下文

    在响应式中,大部分情况是禁止使用ThreadLocal的(可能造成内存泄漏).因此基于ThreadLocal的功能都无法使用,reactor中引入了上下文,在一个流中,可共享此上下文
    ,通过上下文进行变量共享以例如:事务,权限等功能.例如:

    
    //从上下文中获取
    @GetMapping
    public Mono<UserInfo> getCurrentUser(){
        return Mono.subscriberContext()
                .map(ctx->userService.findById(ctx.getOrEmpty("userId").orElseThrow(IllegalArgumentException::new));
    }
    
    //定义过滤器设置数据到上下文中
    class MyFilter implements WebFilter{
        public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain){
            return chain.filter(exchange)
                .subscriberContext(Context.of("userId",...))
        }
    }
    
    

    warning 注意:在开发中应该将多个流组合为一个流,而不是分别订阅流.例如:

    //错误
    flux.doOnNext(data->this.save(data).subscribe());
    
    //正确
    flux.flatMap(this::save);
    

    前端请求

    EventSource接口是Web内容与服务器发送的事件的接口。一个EventSource实例打开一个持久连接HTTP服务器,它发送事件的text/event-stream格式。连接保持打开状态,直到通过调用关闭EventSource.close()
    打开连接后,来自服务器的传入消息将以事件的形式传递到您的代码中。如果传入消息中有一个事件字段,则触发的事件与事件字段的值相同。如果不存在任何事件字段,则将message触发通用事件。

    var source = new EventSource(request.createTokenUrl("network/websocket/server/" + id + "/_subscribe/" + data.type));
    printLog("开始订阅");
    source.onmessage = function (ev) {
        printLog(ev.data);
    };
    source.onerror = function (ev) {
        receiveMessage.setValue("");
        printLog("error");
        source.close()
     }
    
    展开全文
  • 通过spring提供的AOP功能方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付.spring的AOP支持允许将一些通用任务如安全,事务,日志等进行集中管理,从而提供了更好的复用
  • 2、响应式编程模型 3、Spring 5.0完全支持Junit 5 4、Spring 5.0引入了JetBrains的Kotlin语言支持 spring 的优势 1、方便解耦,简化开发 通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由 Spring 进行控制...
  • 79、Vue的发展及优点缺点

    千次阅读 2021-06-22 11:18:54
    1)vue两大特点:响应式编程、组件化。 2)vue的优势: 轻量级框架(压索之后20KB大小)、简单易学、双向数据绑定、组件化、数据和结构的分离、虚拟DOM、运行速度快。 vue是单页面应用,使页面局部刷新,不用每次...
  • 解析几种编码器技术原理及优缺点

    千次阅读 2021-03-12 15:05:10
    图 2:编码器码盘的比较(图片来源:CUI Devices) 嵌入式专栏 4 电容编码器的优点 电容编码器的工作原理与数字游标卡尺相同,因此它所提供的解决方案克服了光学和磁性编码器的许多缺点。 事实证明,CUI ...
  • Webflux

    2020-11-26 21:02:45
    用于web开发,功能和springMVC类似,响应式编程实现,异步非阻塞。 关于异步非阻塞: *异步和同步:都是针对调用者。调用者发送请求,如果等到对方回应之后才去做其他事情就是同步。如果发送请求后不用等就去做...
  • JAVA函数式编程

    千次阅读 多人点赞 2019-02-17 22:40:55
    JAVA函数式编程背景常见的编程范式函数式编程的优劣JAVA8中为函数式编程引入的变化JAVA函数式编程可以简单概括基本函数Lambda表达式方法引用Stream流API创建操作中间操作终止从操作并行流级联表达式与柯里化收集器...
  • 函数式编程常用术语

    千次阅读 2017-02-11 20:56:50
    近年来函数式编程这种概念渐渐流行起来,尤其是在React/Vuejs这两个前端框架的推动下,函数式编程就像股新思潮一般瞬间席卷整个技术圈。虽然博主接触到的前端技术并不算深入,可这并不妨碍我们通过类似概念的延伸来...
  • 一文解决现代编程语言选择困难:命令式编程

    万次阅读 多人点赞 2021-04-07 16:22:41
    如何了解某种编程语言的优缺点?某种编程语言是否适用于我的项目?面对此类问题,如果求助于搜索引擎,输入“最佳编程语言”,结果会罗列一堆文章,涵盖 Python、Java、JavaScript、C#、C++、PHP 等,并且大多对各...
  • 响应式开发原理

    千次阅读 2018-06-19 22:59:50
    就是在不同终端设备上和任何尺寸的屏幕上也可以展示完美的设计响应式网站的概念:flexible grid layout 弹性网格布局flexible image 弹性图片media queries 媒体查询响应式网站的优点:减少工作量 网站、设计...
  • 前端框架Vue、angular、React的优点缺点 学习web前端开发中,会有很多的框架,那么目前流行的框架有哪些呢? 一、Vue.js: 其实Vue.js不是一个框架,因为它只聚焦视图层,是一个构建数据驱动的Web界面的库。 Vue...
  • Vue.js的优缺点详解

    万次阅读 2019-03-30 19:55:00
    简而言之:Vue.js是一个构建数据驱动的 web 界面的渐进框架。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。核心是一个响应的数据绑定系统。 二、Vue的特点和优势 1、vue两大特点:...
  • 敏捷模型 - 优点缺点 敏捷方法最近在软件世界中被广泛接受。但是,这种方法可能并不总是适用于所有产品。以下是敏捷模型的一些优缺点。 敏捷模型的优点如下 - 是一种非常现实的软件开发方法。 ...
  • 在预算允许的情况下,一个完全定制的“移动”版网站比响应式设计更适合。 网站不必在所有浏览器中表现一致 客户->思维定式->说服引导(理由如下) 允许页面显示效果在老旧浏览器中有细微的差别,这样...
  • 高性能/多核/并发编程领域——本书让锁从此变成过去时。 程序员职业生涯领域——本书让普通程序员得以和数学进行接驳。 本书在.NET 开发领域中的意义 作为广州.NET 技术俱乐部主席、中国香港Azure/.NET 技术俱乐部...
  • 基于PC的工业控制系统的优缺点分析

    万次阅读 2016-03-16 18:32:08
    但是,以任何方式修改Windows系统都不再被认为是开放结构,而是专用的PC控制系统,有它自己的局限和支持标准。所以一般认为,PC控制的新希望是Windows CE操作系统,它占用空间非常小、具有实时性能,并且开放部分...
  • 23种设计模式的优缺点

    千次阅读 2021-01-27 21:06:01
    针对接口编程,不要针对实现编程 优点:可以减少类之间的耦合性、提高系统稳定性、提高代码可读性和可维护性,可降低修改程序所造成的风险。 三、单一职责原则 定义:不要存在多于一个导致类变更的原因。一个类\接口...
  • 客观评价golang的优缺点

    千次阅读 2019-05-21 18:19:10
    Go 语言的优点缺点和令人厌恶的设计 Donng·2018-05-06 22:44:53· 14289 次点击 ·预计阅读时间 31 分钟·大约5小时之前开始浏览 https://studygolang.com/articles/12907?fr=sidebar 这是一个创建于2018-05-...
  • vue优缺点详解

    千次阅读 2021-06-19 11:12:26
    本文就来为大家介绍一下vue的优缺点,希望对大家有一定的帮助。一、Vue是什么Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API。简而言之:Vue.js是一个构建数据驱动的 web 界面的渐进框架...
  • 而对于实时操作系统,主要任务是对事件进行实时的处理,虽然事件可能在无法预知的时刻到达,但是软件必须在事件随机发生时,在严格的时限内做出响应(系统的响应时间)。即使是系统处在尖峰负荷下,也应如此,系统时间...
  • 多种前端框架的优缺点

    千次阅读 2019-03-01 11:54:10
    Web前端目前现有的UI框架:Bootstrap、...UI框架优缺点具体可参考:https://blog.csdn.net/qq_41852103/article/details/79619250 Web前端目前现有的JS框架:JQuery、Zepto、VueJS、AngularJS、ReactJS、backbo...
  • vue的优缺点

    千次阅读 2020-05-15 13:50:52
    VUE官方的解释 Vue 是一套用于构建用户界面的渐进框架。与其它大型框架不同的是,Vue 被设计为可以自...vue的优点 1、简单易用 2、灵活渐进 3、轻量高效 (3-1)、压索之后20KB大小 (3-2) 、虚拟DOM 4、MVVM (4-
  • 学习web前端开发中,会有很多的框架,那么目前流行的框架有... Vue.js通过简单的API(应用程序编程接口)提供高效的数据绑定和灵活的组件系统。 Vue.js的特性如下: 1.轻量级的框架 2.双向数据绑定 3.指令 4....
  • 工厂模式,优缺点以及存在的意义1.简单工厂模式(静态工厂模式)1.工厂方法模式 工厂模式的本质 实例化对象不使用new,用工厂方法代替 将选择实现类,创建对象统一管理和控制。从而将调用者跟我们的实现解耦 - ...
  • 微服务概念及优缺点

    万次阅读 多人点赞 2019-05-29 14:42:09
    开发简单直接,集中管理, 基本不会重复开发 功能都在本地,没有分布式的管理开销和调用开销。 它的缺点也非常明显,特别对于互联网公司来说: 开发效率低:所有的开发在一个项目改代码,递交代码相互...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 38,842
精华内容 15,536
关键字:

响应式编程优点缺点

友情链接: rcictionaldatabase.rar