2017-01-25 1 views
1

Я не знаю, может быть, это антипаттерн.Абстрактная функция, чтобы позволить возвращать обещания или обратный вызов

Скоро очень молодые разработчики присоединятся к нашей команде разработчиков, и я хотел бы позволить им выбрать, хотите ли они использовать модуль с обратным вызовом или шаблоном обещаний.

Эта функция в основном сохраняет данные в базе данных. Я повторяю поток db.insert, чтобы абстрагировать функцию, но есть ли другой способ сделать это?

function create(data, callback) { 
 
    
 
    if(callback) { 
 
    db.insert(data, function(err, doc) { 
 
     return callback(err, doc); 
 
    }); 
 
    
 
    
 
    } else { 
 
    return new Promise(function(res, rej) { 
 
     db.insert(data, function(err, doc) { 
 
     if(err) { 
 
      return reject(err); 
 
     } 
 
     return resolve(doc); 
 
     
 
     }); 
 
    }); 
 
    } 
 
}

+0

Я бы не стал называть это анти-шаблоном. Многие библиотеки работают таким образом. Однако я бы избегал смешивать обещания и обратные вызовы в одной и той же кодовой базе, вместо того, чтобы позволить отдельным разработчикам решать. Если ваш новый разработчик не устраивает обещания, он/она должен их изучить. –

ответ

0

Вы можете просто реализовать функцию обратного вызова, а затем использовать модуль pify добавить обещание.

0

Вы можете просто реализовать обычную функцию CPS (стиль продолжения прохождения) и включить общую функцию promisify, которая адаптирует функции cps для функций возврата в обе стороны.

function create (data, k) { 
    db.insert(data, k) 
} 

function promisify (f) { 
    return function (...args) { 
    return new Promise (function (resolve, reject) { 
     f (...args, function (err, result) { 
     if (err) 
      reject(err) 
     else 
      resolve(result) 
     }) 
    }) 
    } 
} 

Вы можете использовать его с продолжением, как этот

create (data, function(err, res) { 
    if (err) 
    // do something with the error 
    else 
    // do something with the result 
}) 

Или вы можете использовать обещания как этот

promisify(create)(data) 
    .then(res => { 
    // do something with the result 
    }) 
    .catch(err => { 
    // do something with the error 
    }) 

Вы заметите, что функция create довольно лишними Тхо. На самом деле нет необходимости обертывать db.insert следующим образом. Вместо этого пропустить создание функции create и просто использовать оба, как этот

// for cps, use normal api 
db.insert(data, function(err, res) { ... }) 

// for promises, use the wrapper 
promisify(db.insert)(data).then(...) 
1

Мне нравится Bluebird .asCallback(...) подход:

function somethingAsync(cb) { 
    return somePromise().asCallback(cb); 
} 

... по существу, вы возвращаете обещание и вызова обратного вызова (если кто-то был принят). Поэтому его можно использовать в любом случае. Если вы не хотите принимать Bluebird, вы можете по существу сделать то же самое:

function somethingAsync(cb) { 
    var promise = somePromise(); 
    if (!cb) return promise; 

    promise.then(res => cb(null, res), err => cb(err)); 
}