Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/426.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 我有一系列的Rx.主题(a->;B->;C->;a),但最后一步不起作用_Javascript_System.reactive_Reactive Programming_Rxjs_Reactive Extensions Js - Fatal编程技术网

Javascript 我有一系列的Rx.主题(a->;B->;C->;a),但最后一步不起作用

Javascript 我有一系列的Rx.主题(a->;B->;C->;a),但最后一步不起作用,javascript,system.reactive,reactive-programming,rxjs,reactive-extensions-js,Javascript,System.reactive,Reactive Programming,Rxjs,Reactive Extensions Js,我对Rx*完全陌生。在我的论文中,我正在尝试使用RxJS创建一个反应式版本的MVC。它松散地基于 在开始编写代码之前,我可能应该对RxJS进行更多的研究,但我意识到我通常通过跳入池的最深处来学习。但是现在我完全被卡住了 该视图有一个带有数值和按钮的文本字段。按下按钮可更改文本的颜色,单击文本可迭代数值。该值存储在模型中,以便“链”遍历所有三个对象(视图->控制器->模型->视图)。按下按钮不需要模型,因此链为视图->控制器->视图 其他一切都正常,但链(->视图)的最后一部分给我带来了麻烦。单击

我对Rx*完全陌生。在我的论文中,我正在尝试使用RxJS创建一个反应式版本的MVC。它松散地基于

在开始编写代码之前,我可能应该对RxJS进行更多的研究,但我意识到我通常通过跳入池的最深处来学习。但是现在我完全被卡住了

该视图有一个带有数值和按钮的文本字段。按下按钮可更改文本的颜色,单击文本可迭代数值。该值存储在模型中,以便“链”遍历所有三个对象(视图->控制器->模型->视图)。按下按钮不需要模型,因此链为视图->控制器->视图

其他一切都正常,但链(->视图)的最后一部分给我带来了麻烦。单击文本(在视图中)会将更改传播到控制器和模型,但不会通知视图模型中的更改。我不明白为什么,因为我理解这一切的方式都是以同样的方式实现的

我在下面的代码示例中添加了注释,以指定未被调用的函数

代码是可用的。请注意,正如我所说,这些代码是为我的论文编写的,因此一些设计决策和应用程序本身可能看起来很奇怪。下面我也试着把我觉得最相关的部分包括进去。我知道我应该提供一个完整的例子,但在这种情况下是不可能的

对象得到的“obs”参数是一个内部数据结构,我用它来存储可观察的对象。相关部分是

var OBSERVABLES = {
    observe: function(source, observer, observer_name) {
      this.request(source, function(s) {
        console.log("\t[" + source + " is being observed by " + observer_name + " (" + s.constructor.name + " -> " + observer.constructor.name + ")]")

        return s.subscribe(
          function myOnNext(x) {
            console.log("\t(" + source + ") " + s.constructor.name + " -> OnNext -> (" + observer_name + ") " + observer.constructor.name)
            observer.onNext(x)
          },
          function myOnError(err) {
            console.log(error)
          })
      })
    },
View.js

var modelAmount = new Rx.Subject()
var textClicks = new Rx.Subject()
var buttonClicks = new Rx.Subject()
var changeColors = new Rx.Subject()

function View(obs, div) {
  console.log("View :: New View")
  obs = obs
  div = div
  var self = this

  obs.observe("clickAmount", modelAmount, "modelAmount")
  obs.observe("changeColor", changeColors, "changeColors")
  obs.add("textClicks", textClicks)
  obs.add("buttonClicks", buttonClicks)

  //Draw HTML elements
  render(div);
}
...
function onClick() {
  console.log("View :: onClick() emits 'textClicks'");
  textClicks.onNext()
}

function onButtonClick() {
  console.log("View :: onButtonClick() emits 'buttonClicks'");
  buttonClicks.onNext()
}

//Listen to controllers instruction to change the color
// DOES NOT WORK
var changeNumberColor = changeColors.map(function(c) {
  console.log("View :: Listened to 'changeColor'")
  if (c === undefined) {
    c = getColor()
  }

  CONTENT.css('color', c)
});

//Listen to model's instruction to change the value
// DOES NOT WORK
var setValue = modelAmount.last(function(latestValue) {
  console.log("View :: Listened to 'clickAmount'")
  console.log("View :: setValue(" + latestValue + ")")
  CONTENT.text(latestValue)
});
Controller.js

  var inputTextClicks = new Rx.Subject();
  var inputButtonClicks = new Rx.Subject();

  var obs = null;

  function Controller(obs){
    console.log("Controller :: New Controller")
    obs = obs

    obs.observe("textClicks", inputTextClicks, "inputTextClicks")
    obs.observe("buttonClicks", inputButtonClicks, "inputButtonClicks")

    obs.add("addAmount", addAmount);
    obs.add("changeColor", changeColor);
  }

  //Listen to input events and give instructions to model
  var addAmount = inputTextClicks.map(function(){
    console.log("Controller :: addAmount() listened to 'textClicks' and emits 'addAmount'")
    return 1;
  });

  //Listen to button presses and give instructions to the view
  var changeColor = inputButtonClicks.map(function(){
    console.log("Controller :: ChangeColor() listened to 'buttonClicks' and emits 'changeColor'")
    return 1;
  });
Model.js

  var controllerAddAmount = new Rx.Subject();

  var obs = null;

  //Stores the texts value. Starts at 0
  var VALUE = 0;

  function Model(obs){
    console.log("Model :: New Model")
    obs = obs

    obs.observe("addAmount", controllerAddAmount, "controllerAddAmount")
    obs.add("clickAmount", amountChanged)
  }

  //Listen to the controller about changing the value, notify the view about the new value
  var amountChanged = controllerAddAmount.map(function(val){
    console.log("Model :: amountChanged() listened to 'addAmount' and emits 'clickAmount'")
    VALUE += val
    console.log("Model :: Amount Changed to " + VALUE)
    return VALUE;
  })

所以问题是View.setValue()和View.setNumberColor()。

您有很多代码基本上如下所示:

// Listen to x to ...
var a = x.map(function (val) { ... });
但是你永远不会展示你用
a
做了什么<代码>映射获取一个可观察对象并生成一个新的可观察对象,该可观察对象将运行提供的映射操作。但是,它返回的可观察对象是惰性的,除非您最终订阅
a
(或
a
)的某个派生版本,否则实际上不会做任何事情

对于您的控制器和模型,您似乎最终订阅了它们正在生成的观测值(通过将它们添加到您的
obs
,然后在视图中订阅它们的迂回路线)

但是,您是否订阅过
changeNumberColor
modelmount
,目前尚不清楚。基于这两个
map
方法中的命令式代码,我猜在这两种情况下,您应该使用
subscribe
而不是
map


另外,对于
modelmount
而言,您错误地使用了
last
运算符。最有可能的情况是,您认为
last
做了一些不同于它的事情。

请更具体一点。好的,我会试试。创建一个更好的例子是困难的,这就是为什么我提供了链接。编辑:我改进了标题。你说的更具体是什么意思?谢谢你的回答!就像我说的,我是一个Rx新手,所以如果我完全放弃了我想做的一些事情,我不会感到惊讶。如果我正确理解您的建议,我应该将代码更改为“var changeNumberColor=changeColors.subscribe(..”?这段代码的循环性质可能让我这样的新手更难理解。明天我将尝试解决这个问题,可能会编辑此评论,或者添加一条新评论。
var changeNumberSubscription=changeColors.subscribe(…)
。当你订阅时,你是说你想观察可观察的事物,并在值到达时做些事情。当你想停止观察时,它会返回一个你可以使用的一次性工具。它成功了!非常感谢你。我认为我这样做可能是错误的,因为现在我订阅了两次相同的流。或者别的什么。也许我会尝试在不使用“obs”构造的情况下重新创建这个示例,而这种构造似乎只会使问题变得更加复杂。是的,
obs
构造最好通过添加
.do()
操作符来记录可观察链不同阶段的消息。