Reputation: 6632
I am working on server that uses hapi
and executes rules from node-rules
.
I have a callback which is called by the R.execute
method from node-rules
. I need to return a Promise
from the exec
method as the result of executing the callback
.
Code
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)
}
}
I noticed from the source code that R.execute
does not return anything that I can use. I notice that in execute
calls this function here recursively but does not terminate without the callback.
How can I convert this to a function that returns a Promise?
Upvotes: 0
Views: 513
Reputation: 6632
While browsing through some of the answers for other questions, I remembered the $.deferred
and Q.defer
API, I found a solution that resembles them:
creates a deferred
passes the deferred to the callback
uses the deferred
and resolve the promise
and most importantly, return the promise
that was created by the deferred
I did not want a custom Promise implementation or to monkey-patch the
Promise
API. If the latter is not a problem, there are several modules on npm which do this and polyfillPromise.defer
.
The defer
function is from here
The code now looks like:
/* 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
}
}
Upvotes: 0
Reputation: 5704
Not sure if i understand correctly but something like this might do
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>')
}
})
}
Upvotes: 0