Преобразование обратного вызова в 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, я нашел решение, которое напоминает их:

  1. создает отложенный

  2. передает отложенное в обратный вызов

  3. использует deferred и выполнить обещание

  4. и самое главное, вернуть promise который был создан deferred

Я не хотел, чтобы пользовательская реализация Promise или мартышка-патч Promise API. Если с последним нет проблем, на npm есть несколько модулей, которые делают это и polyfill Promise.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>')
        }
    })
}
Другие вопросы по тегам