0

我刚开始学习秘银,我正在尝试编写一个与 RESTful API 交互的简单前端。但是,当我在浏览器中加载它时,浏览器每秒向“/posts”发出 < 30 个 GET 请求!我不确定这是否是我的代码中的错误或秘银如何工作......我怎样才能让 m.request 在整个代码中发出一次请求,或者任意更新 Post.list?

var Post = {
  model: function(data) {
    data = data || {};
    this.id = m.prop(data.id);
    this.text = m.prop(data.text);
    this.rating = m.prop(data.rating);
    this.created_at = m.prop(data.created_at);
    this.url = m.prop(data.url);
    this.title = m.prop(data.title);
    this.user_id = m.prop(data.user_id);
  },
  list: function() {
    return m.request({
      method: "GET",
      url: "/posts/",
      type: Post.model
    });
  }
}
var PostIndex = {
  controller: function() {
    this.posts = Post.list();
  },
  view: function(ctrl) {
    return [
      m("table.table", [ m("tbody", [
        ctrl.posts().map(function(post) {
          return m("tr", [
            m("td.heading", { onclick: m.route('/posts/' + post.id) }, [
              post.title,
              m("small", post.url)
            ]),
            m("td", [ m("small", post.user + ": " + post.created_at) ])
          ]);
        })
      ])])
    ];
  }
};
4

1 回答 1

2

Mithril 在内部使用一种称为虚拟 DOM 的东西。其工作方式是有一个 DOM 的内存模型,每当您的模型对象中的某个内容发生更改或用户与页面交互时,该模型就会更新。基本上,一直。这一切都发生在内存中,并且经过优化可以非常快速地工作。每次重新创建虚拟 DOM 时,它都会将自己与实际 DOM 进行比较,看看是否有任何差异。如果有什么不同,只有这样 Mithril 才会更新实际的 DOM。这是秘银如此之快的部分原因。

我不肯定,但 m.request 可能会从视图函数中调用,该函数一直触发(以更新虚拟 DOM)。

ctrl.posts().map(function(post) {
      return m("tr", [.....

如果是这种情况,那么这里发生的情况如下: ctrl.posts() -> Post.list() -> m.request

一个可能的解决方案是在 m.request 完成执行后存储它的结果,然后与其他任何地方的存储值相关联。您可以将控制器代码更改为以下内容:

controller: function() {
    this.posts = m.prop([])
    Post.list().then(this.posts, console.log)
},

这首先使用 getter/setter 函数初始化 this.posts,该函数现在将返回一个空列表。然后它调用 m.request 函数,该函数将发送一次 GET 请求。一旦请求结束,结果将传递给“then”函数。"then" 将函数作为参数:第一个 - 如果前面的函数成功了怎么办,第二个 - 如果它失败了怎么办。无论哪种方式,传递的函数都会自动接收前一个函数的结果,因此不需要显式指定。由于 this.posts 现在是一个通过传递参数设置的函数,因此 this.posts 将自动设置 m.request 调用的结果。

在此更改之后,当在视图函数中调用 ctrl.posts 时,它将在存储在变量中的内容上调用,而不是每次都向 m.request 发送垃圾邮件。

我目前正在自己​​学习秘银并且玩得很开心。我不肯定我所描述的就是这里发生的事情,但听起来像这样的事情。如果我的建议没有帮助,可能是您的代码在每次调用 ctrl.posts() 时都发送 AJAX 请求,直到第一个请求完成。所以我会检查请求是在一段时间后停止,还是一直继续,因为这可能有助于缩小可能的范围。

于 2015-09-08T17:12:15.710 回答