Promisfy петлевые модели

В модульном тестировании Loopback необходимо использовать обратные вызовы с методами upsert. Так, например... вместо того, чтобы писать что-то вроде этого:

before(function () {

    Student = server.models.Student
    Course = server.models.Course


    Course.upsert({id: 1, key: 'A', department: 'Original department'})
    Student.upsert({id: 1, points: 5000})


})

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

before(function (done) {

    Student = server.models.Student
    Course = server.models.Course


    async.waterfall([
            function (callback) {
                Course.upsert({id: 1, key: 'A', department: 'Original department'}, callback)
            },
            function (f, callback) {
                Student.upsert({id: 1, points: 5000}, callback)
            },

        ],
        function (err, results) {
            done(err)
        })

})

Вместо асинхронного, как изменить приведенный выше код, чтобы использовать промисы?

Я думаю, что с промисами я смогу написать некоторый код, который выглядит так:

before(function (done) {

    Student = server.models.Student
    Course = server.models.Course


    Course.upsert({id: 1, key: 'A', department: 'Original department'})
      .then(Student.upsert({id: 1, points: 5000})
      .then(function(err) { done(err) } 


})

но я безуспешно связывал обещания.

ИЗМЕНИТЬ из ответов ниже...

 before(function (done) {


    Course = server.models.Course

    Course.upsertWithPromise = Promise.promisify(Course.upsert)

    Course.upsertWithPromise({id: 1, key: 'A', department: 'Original department'})
        .then(done)

  } 




it.only('Course upsert', function (done) {

    Course.findById(1, function (err, course) {

        expect(course.id).to.equal(1)
        expect(course.department).to.equal('Original department')

        done()


    })
})

person user465342    schedule 11.03.2016    source источник


Ответы (1)


Есть два возможных решения. Во-первых, это ручное обещание. Ваши функции будут выглядеть так:

server.models.Student.upsert = function(data) {  // Note NO CALLBACK
  return new Promise(function(resolve, reject) {
    // Here can do all async staff and when done sucessfully call:
    resolve(result);
    // OR on error call:
    reject(err);
  });
}

Второе решение будет использовать библиотеку для той же цели.

  1. вар q = требуется ('q'); // Используем библиотеку q
  2. НЕ изменяйте свои модели. Они должны принимать обратный вызов в качестве последнего аргумента (следуйте соглашению об узлах).
  3. var server.models.Student.upsertWithPromice = q.denodeify(server.models.Student.upsert);
  4. выгода.

Тогда ваш код из вашего примера должен работать нормально.

person Sergey Yarotskiy    schedule 11.03.2016
comment
Это здорово и очень полезно! Вы упоминаете q вместо Bluebird. Подходит ли q для такого рода обещаний? - person user465342; 11.03.2016
comment
Обе библиотеки похожи и имеют почти одинаковую функциональность. Я просто использую Q и имею для этого живой пример. - person Sergey Yarotskiy; 11.03.2016
comment
Имеет смысл. Отредактировал исходный вопрос с теми изменениями, которые вы предлагаете. Как отмечено в вопросе, не находит идентификатор :( - person user465342; 11.03.2016
comment
Измененный пример для использования bluebird ... работал как шарм. - person user465342; 11.03.2016