Обвиване на Node.js обратни извиквания в Promises с помощта на Bluebird

Как да обвия обратно извикване на Node.js с помощта на Promise в Bluebird? Ето какво измислих, но исках да знам дали има по-добър начин:

return new Promise(function(onFulfilled, onRejected) {
    nodeCall(function(err, res) {
            if (err) {
                onRejected(err);
            }
            onFulfilled(res);
        });
});

Има ли по-чист начин да направите това, ако трябва да се върне само грешка?

Редактиране Опитах се да използвам Promise.promisifyAll(), но резултатът не се разпространява към клаузата then. Моят конкретен пример е показан по-долу. Използвам две библиотеки: a) sequelize, която връща обещания, b) supertest (използвана за тестване на http заявки), която използва обратни извиквания в стил възел. Ето кода без използване на promisifyAll. Той извиква sequelize за инициализиране на базата данни и след това прави HTTP заявка за създаване на поръчката. И двата оператора console.log са отпечатани правилно:

var request = require('supertest');

describe('Test', function() {
    before(function(done) {
        // Sync the database
        sequelize.sync(
        ).then(function() {
            console.log('Create an order');
            request(app)
                .post('/orders')
                .send({
                    customer: 'John Smith'
                })
                .end(function(err, res) {
                    console.log('order:', res.body);
                    done();
                });
        });
    });

    ...
});

Сега се опитвам да използвам promisifyAll, за да мога да свържа обажданията с след това:

var request = require('supertest');
Promise.promisifyAll(request.prototype);

describe('Test', function() {
    before(function(done) {
        // Sync the database
        sequelize.sync(
        ).then(function() {
            console.log('Create an order');
            request(app)
                .post('/orders')
                .send({
                    customer: 'John Smith'
                })
                .end();
        }).then(function(res) {
            console.log('order:', res.body);
            done();
        });
    });

    ...
});

Когато стигна до втория console.log аргументът res е недефиниран.

Create an order
Possibly unhandled TypeError: Cannot read property 'body' of undefined

какво правя грешно


person Naresh    schedule 31.03.2014    source източник
comment
възможен дубликат на Как да конвертирам съществуващ API за обратно извикване в обещания?   -  person Bergi    schedule 31.03.2014
comment
Вижте моя редактиран отговор (коментиране за известие)   -  person Esailija    schedule 31.03.2014
comment
Имате .then свързан към .then, който не връща нищо. Вашият оригинален въпрос е дубликат и вашата редакция е свързана само с правилното използване на .then манипулатори.   -  person Benjamin Gruenbaum    schedule 31.03.2014


Отговори (1)


Вие не извиквате версията за връщане на обещанието и също не я връщате.

Опитайте тази:

   // Add a return statement so the promise is chained
   return request(app)
            .post('/orders')
            .send({
                customer: 'John Smith'
            })
            // Call the promise returning version of .end()
            .endAsync(); 
person Esailija    schedule 31.03.2014
comment
Страхотно! Това реши проблема ми. Имаше лека грешка. Извикването на request(app) всъщност връща тестов обект (вижте тук: github .com/visionmedia/supertest/blob/master/index.js#L19-34). Така че трябваше да променя извикването на promisify на Promise.promisifyAll(request.Test.prototype). За щастие, request.Test беше разкрит. Какво трябваше да направя, ако не беше? Освен това какво ще стане, ако всички методи на обекта не са предназначени да приемат обратно извикване или обратното извикване не е задължително? Безопасно ли е използването на promisifyAll() в тези случаи? Благодаря за вашата помощ. - person Naresh; 31.03.2014
comment
@Naresh, ако класът няма да бъде изложен, можете да направите Promise.promisifyAll(request().constructor.prototype) (извън всеки код, това трябва да се направи само веднъж за целия живот на приложението) - person Esailija; 31.03.2014
comment
@Naresh Няма значение какви функции има, ако не ги извиквате. Ако извикате someMethodAsync() и someMethod не е функция за обратно извикване, това просто ще причини странни грешки - но защо бихте извикали someMethodAsync(), като знаете, че someMethod не е функция за обратно извикване? :P - person Esailija; 31.03.2014
comment
Отлично! Отговорихте на всичките ми бавни въпроси. Всъщност, препрочитайки документите, всички отговори са там, но не ми изскочиха. Може би прост специфичен пример за node.js на началната страница на Bluebird би помогнал. Примерът, който започва с Можете също да използвате обещания за подобряване на код, който е написан с помощници за обратно извикване, е малко прекалено сложен за мен - не го свързах с обратно извикване на Node.js и затова стигнах до първото решение, посочено в моя въпрос (този, който създава ново обещание ръчно). Още веднъж благодаря за помощта. - person Naresh; 31.03.2014
comment
@Naresh Благодаря за обратната връзка, ще измисля нещо - person Esailija; 31.03.2014