Преобразование обратного вызова в Promise, когда у меня нет возвращаемого значения
Я работаю на сервере, который использует hapi
и выполняет правила из node-rules
,
У меня есть обратный вызов, который вызывается R.execute
метод из node-rules
, Мне нужно вернуть Promise
от exec
метод в результате выполнения callback
,
Код
const callback = data => {
const {matchPath, result} = data
descision.setMatchPath(matchPath)
if (!result) {
descision.addMessage(
'No match could be found in the rules provided, either incorrect or non-matching information was provided'
)
}
}
function exec (input) {
const {medicineType, facts: data} = input
const R = new RuleEngine()
R.register(rules)
if (medicineType !== 'generic') {
const facts = {
data
}
R.execute(facts, callback)
}
}
Я заметил из исходного кода, что R.execute
не возвращает ничего, что я могу использовать. Я заметил, что в execute
вызывает эту функцию здесь рекурсивно, но не завершается без обратного вызова.
Как я могу преобразовать это в функцию, которая возвращает обещание?
2 ответа
Просматривая некоторые ответы на другие вопросы, я вспомнил $.deferred
а также Q.defer
API, я нашел решение, которое напоминает их:
создает отложенный
передает отложенное в обратный вызов
использует
deferred
и выполнить обещаниеи самое главное, вернуть
promise
который был созданdeferred
Я не хотел, чтобы пользовательская реализация Promise или мартышка-патч
Promise
API. Если с последним нет проблем, на npm есть несколько модулей, которые делают это и polyfillPromise.defer
,
defer
функция отсюда
Код теперь выглядит так:
/* eslint-disable promise/param-names */
function defer () {
let resolve, reject
const promise = new Promise(function (...args) {
resolve = args[0]
reject = args[1]
})
return {resolve, reject, promise}
}
/* eslint-enable promise/param-names */
const makeCallback = deferred => data => {
const {matchPath, result} = data
descision.setMatchPath(matchPath)
if (!result) {
descision.addMessage(
'No match could be found in the rules provided, either incorrect or non-matching information was provided'
)
}
deferred.resolve(descision)
}
function exec (input) {
const {medicineType, facts: data} = input
const R = new RuleEngine()
R.register(rules)
if (lenderType !== 'generic') {
const facts = {
data
}
const deferred = defer()
const callback = makeCallback(deferred)
R.execute(facts, callback)
return deferred.promise
}
}
Не уверен, правильно ли я понимаю, но что-то подобное может сделать
function exec(input) {
const { medicineType, facts: data } = input
const R = new RuleEngine()
R.register(rules)
return new Promise(function(resolve, reject) {
if (medicineType !== 'generic') {
const facts = {
data
}
R.execute(facts, function(data) {
const { matchPath, result } = data
descision.setMatchPath(matchPath)
if (!result) {
descision.addMessage(
'No match could be found in the rules provided, either incorrect or non-matching information was provided'
)
}
resolve('<return here whatever you want>')
// or
// reject('<return some error>')
});
} else {
reject('<return some error>')
}
})
}