Выполнение асинхронной операции в обещании bluebird

Итак, я бил это в течение нескольких дней, и я в тупике относительно того, как лучше всего решить эту проблему. Я использую Waterline/dogwater с HAPI и пытаюсь сделать что-то вроде этого: -

wardrobe.find({WardrobeId: 5}).then(function(clothes) {
    //got my clothes in my wardrobe.
    clothes.find({Type: 'trousers'},{Kind: 'nice ones'}).then(function(trousers) {
        //got my nice trousers
        _.each(trousers, function(trouser) {
            //logic to see if these are my pink trousers
            console.log('color?', trouser.color);
        });
        console.log('ding');
    });
});

У меня проблема в том, что код всегда будет ding до того, как выведет цвета брюк. Это потому, что, насколько я понимаю, _.each сделает код асинхронным. Я пытался внедрить Promises (bluebird), но безуспешно. Я даже посмотрел на генераторы (Co), но моя версия узла исправлена ​​до v0.11.

Я хотел бы выполнить некоторые поиски в базе данных в _.each, вернуть эти результаты (если есть) в объект брюк, который затем может быть возвращен: -

wardrobe.find({WardrobeId: 5}).then(function(clothes) {
    //got my clothes in my wardrobe.
    clothes.find({Type: 'trousers'},{Kind: 'nice ones'}).then(function(trousers) {
        //got my nice trousers
        _.each(trousers, function(trouser) {
            //logic to see if these are my pink trousers
            db.colors.find({Color: trouser.color}).then(function(color) {
                //color here?
            });
        });
        console.log('ding');
    });
});

Как лучше всего сделать это максимально эффективно?

Помощь приветствуется. Рад вернуться сюда и сфокусировать вопрос там, где это необходимо.


person dooburt    schedule 13.11.2014    source источник
comment
Вы можете использовать асинхронный код js, например блокирующий код, используя функции ecmascript 6. Взгляните на Task.js (taskjs.org), но я не уверен, поддерживает ли ваша среда js эти es6. апис.   -  person Nick Russler    schedule 13.11.2014
comment
Предполагая, что подчеркивание/lodash - _.each не является асинхронным.   -  person Benjamin Gruenbaum    schedule 13.11.2014
comment
@BenjaminGruenbaum Но db.colors.find, похоже, возвращает обещание, что делает все это асинхронным. Если yield доступен, вы можете использовать Task.js, чтобы выполнить это обещание, пока оно выполняется.   -  person Nick Russler    schedule 13.11.2014
comment
@NickRussler выглядит хорошо, но нужна ли мне версия 0.11.*+? В настоящее время застрял на версии 0.10.33 в производстве.   -  person dooburt    schedule 13.11.2014
comment
@BenjaminGruenbaum _.each является асинхронным, и ^, как указано выше, код всегда будет звонить до завершения каждого, независимо от размера массива, предоставленного каждому. Если предположить, что это был вопрос?   -  person dooburt    schedule 13.11.2014
comment
Я только что попробовал с v0.10.33, и ключевое слово yield недоступно, извините.   -  person Nick Russler    schedule 13.11.2014
comment
Каждый из них не асинхронный. это синхронный метод. OP просто делает в нем асинхронные вещи.   -  person Benjamin Gruenbaum    schedule 13.11.2014
comment
@BenjaminGruenbaum спасибо за исправление моей _.each дезинформации ;)   -  person dooburt    schedule 13.11.2014


Ответы (1)


Ну _.each не имеет ничего общего с асинхронностью. Это просто способ подчеркивания/lodash сделать trousers.forEach(...).

Ваша проблема связана с методом db.colors.find, который выполняет асинхронную операцию. Вы можете связать методы, если хотите, чтобы они выполнялись последовательно как таковые:

wardrobe.find({WardrobeId: 5}).then(function(clothes) {
    //got my clothes in my wardrobe.
    clothes.find({Type: 'trousers'},{Kind: 'nice ones'}).then(function(trousers) {
        //got my nice trousers
        var p = Promise.resolve();
        _.each(trousers, function(trouser) {
            //logic to see if these are my pink trousers
            p = p.then(function() {
                return db.colors.find({Color: trouser.color})
                    .then(function(color) {
                        // color here, they'll execute one by one
                    });
            });
        });
        p.then(function(){ 
            console.log('ding, this is the last one');
        });
    });
});

Или, если вы хотите, чтобы все они происходили одновременно, а не ждали предыдущего:

wardrobe.find({WardrobeId: 5}).then(function(clothes) {
    //got my clothes in my wardrobe.
    clothes.find({Type: 'trousers'},{Kind: 'nice ones'}).then(function(trousers) {
        //got my nice trousers
        Promise.map(trousers, function(trouser) {
            return db.colors.find({Color: trouser.color});
        }).map(function(color){
            console.log("color", color);
        }).then(function(){ 
            console.log('ding, this is the last one');
        });
    });
});
person Benjamin Gruenbaum    schedule 13.11.2014
comment
Пятно на Бенджамина. Спасибо. +1 - person dooburt; 13.11.2014