2016-12-17 3 views
1

У меня есть список объектов, и я хочу перейти в разные коллекции и сделать базу операций на каждом Id. Я предпочел бы делать операцию один за другим (последовательно)Сделайте несколько обещаний по массиву элементов

var removeOperation = function(objectified){ 
    return Comps.findOne({reviews : objectified}).populate([{ path: "reviews", match : {_id : objectified}}]) 

} 
var firstCheckIfAnonHasTheIdInReviewsArrayIfThereDeleteIt = function(objectified){ 
    var query = {reviews : objectified}; 
    var update = {$pull : {reviews : objectified}}; 
    var option = {new :true}; 
    return Anon.findOneAndUpdate(query, update, option); 
}; 
var thenCheckIfUserHasTheIdInReviewsArrayIfThereDeleteIt = function(objectified){ 
    var query = {reviews : objectified}; 
    var update = {$pull : {reviews : objectified}}; 
    var option = {new :true}; 
    return User.findOneAndUpdate(query, update, option); 
} 

Я шел по этому пути:

Promise.mapSeries(arrOfObjectIds, function(e){ 
    return removeOperation(e); 
}) 
.then(function(results){ 
    console.log(results); 
    var map = results.map(function(e){ 
     // return e.reviews[0] 
     return e 

    }) 
    console.log("map : ", map) 
    return Promise.resolve(map); 
}) 
.then(function(compDocs){ 
    console.log("compDocs: ",compDocs) 
    Promise.mapSeries(compDocs, function(compDoc){ 
     return updateCompAndRemoveReviewFromArray(compDoc) // I know it's not show. It's another promise I use 
    }) 

}).then(function(returned){ 
    return Reviews.remove({_id : {$in : arrOfObjectIds }}) 
}) 
.then(function(){ 
    I wanted to do firstCheckIfAnonHasTheIdInReviewsArrayIfThereDeleteIt on the array of object Ids to delete the review from the array. Also if we succesfully removed the array here we should not have to go to the next user 
    promise which deletes a users review since if we deleted in Anon it won't be in User. since there is only one review ID possible per review. 
}) 
.then(function(){ 
    //if there was no review pulled from the Anon reviews Array. that means it's in the users review and we should do this promise 

     thenCheckIfUserHasTheIdInReviewsArrayIfThereDeleteIt() 
}) 

Так может быть, вы можете показать мне, как использовать mapSeries на массив элементов, так что он просто не обещает, но выполняет несколько обещаний.

мы можем лань что-то вроде:

Promise.mapSeries(arrOfObjectIds, function(e){ 
    return removeOperation(e); 
    return firstCheckIfAnonHasTheIdInReviewsArrayIfThereDeleteIt(e)// extra credit: check if this was successful (review was pulled). If it wasn't got to next one. 
    return thenCheckIfUserHasTheIdInReviewsArrayIfThereDeleteIt(e) 
}) 

ответ

0

Вы можете использовать Array.reduce(), чтобы выполнить свои обещания в серии:

arrOfObjectIds.reduce(function(promise, objectId) { 
    return promise.then(function(result) { 
    return removeOperation(objectId) 
     .then(firstCheckIfAnonHasTheIdInReviewsArrayIfThereDeleteIt) 
     .then(thenCheckIfUserHasTheIdInReviewsArrayIfThereDeleteIt); 
    }); 
}, Promise.resolve()); 

Это будет выполнять цепочку removeOperation -> firstCheck.. -> thenCheck один элемент в массиве в то время, , затем перейдите к следующему элементу.

0

can we doe something like: да, как это, за исключением первого возвращения выходит функция

так, вы могли бы сделать что-то вроде

Promise.mapSeries(arrOfObjectIds, function(e){ 
    return removeOperation(e) 
    .then(function() { 
     return firstCheckIfAnonHasTheIdInReviewsArrayIfThereDeleteIt(e); 
    }).then(function() { 
     return thenCheckIfUserHasTheIdInReviewsArrayIfThereDeleteIt(e); 
    }) 
}) 
1

Подтвердив проблему в упрощенном виде:

You иметь массив идентификаторов и для каждого идентификатора, в свою очередь, вы хотите вызвать три функции возврата посылок, A, B и C как fo llows:

  • A(id) (безусловно)
  • затем B(id) (безусловно)
  • затем C(id) (условно, в зависимости от результата B(id))

Можем ли мы сделать что-то вроде:

Promise.mapSeries(arrOfObjectIds, function(e){ 
    return removeOperation(e); 
    return firstCheckIfAnonHasTheIdInReviewsArrayIfThereDeleteIt(e)// extra credit: check if this was successful (review was pulled). If it wasn't got to next one. 
    return thenCheckIfUserHasTheIdInReviewsArrayIfThereDeleteIt(e) 
}) 

Да, хотя не очень как предложенный код.

Во-первых, у вас есть выбор дизайна относительно способа, которым B сообщает о своем исходе. Вопрос подсказывает, что результат B является случаем «успеха» против «неудачи», но это не единственный способ его моделирования.

Вариант 1: Данные испытаний доставлена ​​вниз путь успеха Обещания цепи было

Записи B таким образом, что возвращающее обещание будет выполнять как в случае успеха (Anon отзыв был удален) или на ожидаемой недостаточности (Anon отзыв не удалялось) и сообщать результат с помощью параметра.

var B = function(objectified) { 
    var query = {reviews: objectified}; 
    var update = {$pull: {reviews: objectified}}; 
    var option = {new :true}; 
    return Anon.findOneAndUpdate(query, update, option).exec(); 
}; 

Тогда можно было бы написать:

Promise.mapSeries(arrOfObjectIds, function(id) { 
    return A(id).then(function() { 
     return B(id); 
    }).then(function(item) { // item will be `null` if B(id) found nothing. 
     return item || C(id); 
    }).catch(function(error) { 
     // If anything went wrong, catch the error and log it. 
     console.log(error); 
     // By not re-throwing the error, the mapseries() is allowed to continue. 
    }); 
}); 

Вариант 2: Ошибка Тест поставляется вниз путь отказа Обещание цепную в

Запись B таким образом, что возвращающий обещание выполнит на успех, или отказаться от ожидаемого отказа.

var B = function(objectified) { 
    var query = {reviews: objectified}; 
    var update = {$pull: {reviews: objectified}}; 
    var option = {new :true}; 
    return Anon.findOneAndUpdate(query, update, option).exec().then(function(item) { 
     return item || Promise.reject(new Error('not found')); 
    }); 
}; 

Тогда можно было бы написать:

Promise.mapSeries(arrOfObjectIds, function(id) { 
    return A(id).then(function() { 
     return B(id).catch(function(error) { 
      // Here, you have to discriminate between the "expected error" and any unexpected errors. 
      if(error.message === 'not found') { 
       return C(id); 
      } else { 
       throw error; // unexpected error - rethrow it 
      } 
     }); 
    }).catch(function(error) { 
     // If anything went wrong, catch the error and log it. 
     console.log(error); 
     // By not re-throwing the error, the overall mapseries() is allowed to continue. 
    }); 
}); 

В обоих вариантах:

  • вернуть подлинное обещание, использовать .exec() в A, B и C. (Как я понимаю Mongoose, без exec() вы получаете то, что имеет метод .then(), но который не является полноправным обещанием).
  • , если вы хотите, чтобы общая последовательность останавливалась при первой ошибке, затем сбросьте ошибку после ее регистрации или полностью опустите окончательный catch().
  • дальнейшие безусловные этапы могут быть добавлены очень просто, до или после условного этапа.

Для меня вариант 2 более логичен, хотя я бы выбрал вариант 1 для большей простоты и эффективности.

Смежные вопросы