使用 background:true 时如何在 MithrilJS 中使用 m.request 的值?

How do I use the value from m.request in MithrilJS when using background:true?

我在一个项目中使用 m.request,因为我有一个可能很长 运行ning 的请求,我想 运行 它与 background:true.但是,该值似乎永远不会设置为生成的 m.prop

我基于此 Stack Overflow answer: http://jsfiddle.net/u5wuyokz/9/

制作了一个带有示例的 jsFiddle

我期望发生的是,对视图的第二次调用应该具有 ctrl.test.data() 中的响应值,但它似乎仍然具有 undefined。在代码的 Point A 处,它记录了正确的值。但是,在 Point B,它记录 false, undefined 然后 true, undefined

我不确定我是否做错了什么,或者这是预期的行为。

来自 jsFiddle 的代码:

var requestWithFeedback = function(args) {
  var completed = m.prop(false)
  var complete = function(value) {
    completed(true)
    return value
  }
  args.background = true
  return {
    data: m.request(args).then(complete, complete).then(function(value) {
        //Point A
        console.log(value);
        m.redraw()
        return value
    }),
    ready: completed
  }
};

var mod = {
        controller : function() {
            this.test = requestWithFeedback({
                method : "POST",
                url : "/echo/json/",
                serialize: serialize, 
                config: asFormUrlEncoded,
                data : {
                    json : "{\"name\" : \"testing\"}"
                }
            });
        },
        view : function(ctrl) {
            //Point B
            console.log(ctrl.test.ready(), ctrl.test.data());
            return m("div", ctrl.test.ready() ? 'loaded' : 'loading');
        }
    };

编辑: 问题是在分配数据之前调用了 m.redraw。相反,您可以为 data 创建一个 m.prop 并让 ajax 请求在完成时分配该值。 requestWithFeedback 将如下所示:

var requestWithFeedback = function(args) {
  var data = m.prop()
  args.background = true
  m.request(args).then(data).then(function() { m.redraw() })

  return {
    data: data,
    ready: function() {return !!data()}
  }
};

这是您的 fiddle 使用此代码的修改版本:http://jsfiddle.net/u5wuyokz/11/

当使用 background: true 时,Mithril 的 components branch or any other system 在与视图相同的 'tick' 中执行控制器,在控制器中创建的 m.request 届时将无法解析他们被各自的观点所调用。

因此,如果您使用 background: true,则 recommended 始终使用 m.requestinitialValue 属性。典型示例是当您请求条目列表时具有 [] 的初始值:

var projectsModule = {
  controller(){
    this.projects = m.request( {
      background   : true,
      initialValue : [],
      url          : '/projects.json'
    } );
  },
  view( ctrl ){
    return m( 'ul', ctrl.projects.map( 
      project => m( 'li', project.name )
    ) )
  }
}

这解决了当他们期望能够以通用方式使用 m.request return 值时视图中断的实际问题,但没有解决您的示例中更复杂的情况,其中需要 ready 标志来指示 'loading' 状态。我有一个使用模型 getter 函数和可选初始值的通用 API。它有 nextthenhasResolvedisPendinggetset 方法:这允许视图在它们的方式上更加灵活查询异步模型的状态。 hasResolved 表示该方法是否已经解析,next return 是一个承诺,它将通过当前请求解析,或者如果 isPending 为假,则在下一个请求被解析时解析.