ค้นหาหรือสร้างจำนวนมากแบบอะซิงโครนัสด้วย ember.js

ฉันจะค้นหาหรือสร้างจำนวนมากด้วย ember.js ได้อย่างไร สิ่งนี้จะเป็นเรื่องง่ายที่จะทำพร้อมกัน (foreach... ดำเนินการต่อหากมีอยู่) แต่การทำงานกับร้านค้าแบบอะซิงโครนัสของ ember ทำให้เกิดค่าใช้จ่ายมากมายในการติดตามสถานะของการดำเนินการ

โดยเฉพาะอย่างยิ่ง ฉันมีตัวแปรสำหรับติดตามจำนวนออบเจ็กต์ที่รอการประมวลผล (createIfNotExistTaskCounter) ดังนั้นฉันจึงสามารถตรวจสอบได้ว่าร้านค้าเสร็จสิ้นการทำงานกับออบเจ็กต์ทั้งหมดที่จะบันทึกเมื่อใด และฉันใช้อาร์เรย์เพื่อติดตามรายการที่เก็บไว้จนถึงตอนนี้ (createIfNotExistQueue) - ฉันไม่สามารถปล่อยให้ร้านค้าจัดการงานนี้ได้ เพราะฉันไม่สามารถนับรายการที่ถูกพบหลังจากบันทึกแล้วได้

ต่อไปนี้เป็นวิธีแก้ปัญหาที่ดีที่สุดของฉันด้านล่าง (รวมถึงใน JS Bin) มีวิธีที่ง่ายกว่าในการทำเช่นนี้หรือไม่?

App = Ember.Application.create({});

App.LSAdapter = DS.LSAdapter.extend({
    namespace: 'whitespace'
});

App.Store = DS.Store.extend({
    adapter: App.LSAdapter
});

App.Fruit = DS.Model.extend({
    name: DS.attr("string")
});


App.IndexRoute = Ember.Route.extend({
  createIfNotExistTaskCounter: 0, // store number of items waiting to be processed
  createIfNotExistQueue: [],      // store a list of the items being added, to prevent duplicate adds

  setupController: function(controller) {
    /* This is a simplified version of a real task I'm trying to acomplish. The code adds a list of objects to the store, only creating them if they don't exist. After the list has been processed, the contents of the store are shown.

    To achieve this end I've used a counter and a queue to keep track of the operations' state. Is there a simpler way to do this? These overheads seem excessive for such a straightforward bulk insert operation.
    */
    var fruitToStore = ["apple", "pear", "banana", "apple"],
      store = this.get('store');

    this.set('createIfNotExistTaskCounter', fruitToStore.length);

    for(var i=0; i<fruitToStore.length; i++) {
      this.createIfNotExist(fruitToStore[i]);
    }
  },

  createListener: function() {
    if(this.get('createIfNotExistTaskCounter') !== 0) return;

    this.get('store').find('fruit').then(function(results) {

      // should only print three fruits, one of each type
      for (var i = 0; i < results.content.length; i++) {
        console.log(results.content[i].get('name'));
      };
    });

  }.observes('createIfNotExistTaskCounter'),


  createIfNotExist: function(f) {
    var store = this.get('store'),
      queue = this.get('createIfNotExistQueue'),
      that = this;

    // prevent duplicate records being created by adding every (distinct) item to a queue
    // the queue is used because there seems to be no way to tell if an item is already (asynchonously) being found / created / saved
    if(queue.indexOf(f) !== -1) {
      that.decrementProperty('createIfNotExistTaskCounter');
      return;
    }
    queue.push(f);


    // find or create
    store.find('fruit', {name: f}).then(function(results) {

      // found...
      if(results.get('length') !== 0) {
        that.decrementProperty('createIfNotExistTaskCounter');
        return;
      }

      // ...else create
      var fruit = store.createRecord('fruit', {name: f});
      fruit.save().then(function() {
        that.decrementProperty('createIfNotExistTaskCounter');
      }, function() {
        console.log("save failed!");
      });

    });

  }
});

person Ollie Glass    schedule 17.10.2013    source แหล่งที่มา


คำตอบ (1)


หากคุณส่งคืนสัญญาจากการเรียกกลับ then คุณสามารถสร้างห่วงโซ่ของสัญญาที่ทำงานเหมือนกับคิวได้

ขั้นแรกคุณเริ่มต้นด้วยการโทรกลับที่ได้รับการแก้ไขแล้ว จากนั้นคุณจึงแทนที่ด้วยออบเจ็กต์ที่สามารถ "จากนั้น" ได้

queue: new Ember.RSVP.resolve,
addToQueue: function() {
  this.queue = this.queue.then(function() {
    return new Ember.RSVP.Promise(function(resolve, reject){
      // something that eventually calls resolve
    })
  })
}

นี่คือ JSBin ที่อัปเดตของฉันสำหรับโค้ดของคุณ: http://jsbin.com/OtoZowI/2/edit?html,console

อาจมีวิธีทำให้เล็กลงมากหากคุณสามารถหาวิธีคืนคำสัญญาการค้นหา / บันทึกที่มีอยู่แทนที่จะสร้างสัญญาใหม่ เล่นนิดหน่อยแต่ต้องกลับไปทำงาน :P

นอกจากนี้คุณยังสามารถรวบรวมคำสัญญามากมายด้วย RSVP.all และแก้ไขได้เมื่อแก้ไขทั้งหมดแล้วเท่านั้น นี่อาจเป็นวิธีแก้ปัญหาที่สะอาดกว่ามาก ขึ้นอยู่กับโค้ดจริงของคุณ ทำการค้นหาทั้งหมด รอจนกว่าจะได้รับการแก้ไขทั้งหมด จากนั้นจึงสร้างอ็อบเจ็กต์ที่หายไป

เอกสาร RSVP มีตัวอย่างที่ดีที่นี่: https://github.com/tildeio/rsvp.js/blob/master/README.md#arrays-of-promises

person zaius    schedule 18.10.2013