灰烬自动保存 - 排队保存请求

时间:2016-08-23 19:41:33

标签: javascript ember.js ember-data ember-cli

例如,用户在文本框内保持按键,并向服务器发送保存请求以保存该值。

通过去抖动推迟后续事件并不起作用,因为每个keyUp都在新的Run循环中运行,不像长时间按住键并输入那样的字符。

所以问题是:A)Ember Way最常用的方法是A)在发送新请求之前等待请求完成,以确保较旧的值不会覆盖较新的值,并且B )确保至少发送最后一个请求,保存最新的用户输入值。

更新:

经过一段时间的探索,似乎是我最初错过的一件重要事情,每次按下一个键时都会导致我的保存运行,而不是每次去抖一次,这个函数是否传递到去抖动方法必须被命名。将保存代码分解并将引用传递给函数可以在2秒的时间间隔内最多保存一次。



  keyUp: function(e) {
    Ember.run.debounce(this, this.saveFieldValue, 2000);
  },
    
  saveFieldValue: function() {
    const field = this.get('field');
    field.save();
  },




UPDATE2:@ nem035以下的答案解决了我的其他要求:排队保存,所以没有任何遗失。辩解有效,但并不能保证。

1 个答案:

答案 0 :(得分:1)

如果您不关心被忽略的事件,那么您对该事件进行去抖动的方法是最常用的方法,可能是您的最佳方法,但这里有一些替代方案:

简单方法(忽略额外事件)

您可以做的一件简单事情就是在操作开始之前将标志初始化为false,设置为true,并在操作完成时重置为false

saveFieldValue: function() {
  if (!this.get('isSaving')) {

    const field = this.get('field');

    this.set('isSaving', true);
    field.save().then(() => {
      this.set('isSaving', false);
    });
  }
}

这类似于你的去抖动方法(额外的事件被忽略)但是我们有一个标志,如果前一个操作还没有完成,就会阻止操作发生。拥有一个标志还可以帮助您在保存数据时显示微调器或禁用在保存期间无法使用的按钮或类似的东西。

复杂方法(额外事件排队)

你可以做的另一件事,如果你不希望在保存数据时吞下/忽略任何事件,而是希望所有事件都发生(最终),那就是创建你自己的事件队列来处理这是通过排队保存事件并按顺序依次运行它们。

此外,您必须处理队列在一段时间后重新检查自身以运行可能在此期间排队的任何任务的情况。

这是一个使用数组作为队列的简单演示:

// ...

queue: null,

init() {
  this._super(...arguments);

  // ...

  // initialize a new queue for each instance
  this.set('queue', Ember.A()); 

  // start the queue process
  this.processQueue();
},

processQueue() {
  const queue = this.get('queue');

  // if the queue is empty, try again in 100ms (this value is arbitrary, see what would work best for you)
  if (Ember.isEmpty(queue)) {
    Ember.run.later(this, this.processQueue, 100);
  } 

  // otherwise remove the oldest field
  // save it
  // and then re-run the queue process
  else {
    // remove and save the oldest-first
    queue.shiftObject().save()
      .then(() => {
        // here we can do success handling for the saved field
      }, () => {
        // here we can do error handling for the saved field
      })
      .then(() => {
        this.processQueue();
      });
  }
},

saveFieldValue: function() {
  const {
    field, queue
  } = this.getProperties('field', 'queue');

  // push the current field value to the queue 
  queue.pushObject(field);
}

这是一个EmberTwiddle示例