2015-01-29 5 views
2

У меня есть результат вызова REST, который содержит список файлов. У каждого файла есть свойства, которые я должен извлечь и разместить в новом массиве. Это просто и легко выполняется с помощью простой петли. Три из свойств, которые мне нужно извлечь, доступны напрямую, а три других свойства имеют тип HATEOAS, которые, другими словами, означают, что для каждого файла в результате я должен сделать три других асинхронных вызова для извлечения его значений.RSVP.js - Несколько асинхронных вызовов функций в массиве

Мой первый инстинкт заключался в использовании RSVP.all() для обработки моих обещаний и сопоставления элементов в новом массиве с соответствующими свойствами в исходном списке файлов с использованием map, но я не могу понять, как этого добиться.

Я хочу достичь чего-то вроде ниже, но я понятия не имею, как я могу получить индекс текущего сопоставленного элемента в itemList, чтобы включить правильный файл с fileList. Как я могу это сделать?

На боковой панели, если я использую RSVP.all() неправильным способом, я рад получить советы!

function createItemList(fileList) { 
    var promise = new RSVP.Promise(function(resolve, reject) { 
     var itemList = []; 

     //For each file in fileList, get the directly accessible properties 
     //and push it to a new array 
     for (var i = 0, file; file = fileList[i]; i++) { 
      currentItem.Name = file.Name; 
      currentItem.LastModified = new Date(file.TimeLastModified).format("dd-MM-yyyy hh:mm:ss"); 
      currentItem.Version = file.MajorVersion + "." + file.MinorVersion; 

      itemList.push(currentItem); 
     } 

     //This is where it starts to get messy... 
     //I want to map each item in the new itemlist to the corresponding properties 
     //in the fileList. If I can include the corresponding file somehow, I could set the 
     //data in the method 'getModifiedBy' and similar. I believe this should work, 
     //but I have no idea how I can achieve this. 
     var modifiedBy = itemList.map(function(item) { 
      return getModifiedBy(item, fileList[INDEX]); 
     }); 

     var checkedOutBy = itemList.map(function (item) { 
      return getCheckedOutBy(item, fileList[INDEX]); 
     }); 

     var eventDate = itemList.map(function (item) { 
      return getEventDate(item, fileList[INDEX]); 
     }); 

     var promises = { 
      promisesModifiedBy: modifiedBy, 
      promisesCheckedOutBy: checkedOutBy, 
      promisesEventDate: eventDate 
     }; 

     RSVP.all(promises) 
      .then(function() { 
      resolve(itemList); 
     }); 
    }); 
    return promise; 
} 

ответ

2

Используйте только одну карту за itemlist, которая возвращает Promise для 3-свойства-объекта. Используйте выделенную вспомогательную функцию для отдельных элементов.

Btw, с new RSVP.Promise вы используете deferred antipattern, в то время как нет абсолютно никакой причины - RSVP.all() уже возвращает вам обещание результата.

function createItemList(fileList) { 
    return RSVP.all(fileList.map(createItem)); 
} 
function createItem(file) { 
    // get the directly accessible properties 
    var currentItem = {}; 
    currentItem.Name = file.Name; 
    currentItem.LastModified = new Date(file.TimeLastModified).format("dd-MM-yyyy hh:mm:ss"); 
    currentItem.Version = file.MajorVersion + "." + file.MinorVersion; 

    return RSVP.hash({ 
     modifiedBy: getModifiedBy(currentItem, file), 
     checkedOutBy: getCheckedOutBy(currentItem, file) 
     eventDate: getEventDate(currentItem, file) 
    }).then(function(asyncprops) { 
     // somehow mix the asyncprops with the currentItem 
     return item; // into a result item 
    }); 
} 
+0

Это работает именно так, как я хочу, чтобы это работало, хотя мне трудно понять, что происходит, даже при отладке! Наверное, мне придется читать обещания. Кроме того, спасибо, что указали на использование отложенного антипаттера! Я не знал об этом! –