How to wrap a callback function in a Parse.Promise - javascript

I have a function:
function foo(aString, function(err, callback) {
//does stuff
}
I need to call that function from the middle of a long series of Parse.Promises.
How can I wrap it in a Parse.Promise?
I've tried:
//...
return new Parse.Promise(function(resolve, reject) {
foo(thatString, function(err, data) {
if(err) return reject(err);
resolve(data);
});
});
}).then(function(data) {
//...
and other variations like Parse.Promise.as() instead of new Parse.Promise()
Any help would be appreciated.

You're on the right track, but Parse's promise constructor doesn't take resolve / reject functions. Instead, have your wrapper build and return a promise without params, then invoke that promise's resolve() or reject() methods in the wrapped function's callback, like this:
var wrappedFoo = function(aString) {
var promise = new Parse.Promise();
foo(aString, function(err, data) {
if (err) { promise.reject(err); }
promise.resolve(data);
});
return promise;
};
Call it like this:
wrappedFoo("bar").then(function(data) {
// data will be the data passed to the foo callback
}, function(err) {
// likewise for err
});

Related

How to return to the distances out of the function scope

I am new to node js and I have a function where I should pass the source and destinations and then the result will be distance among the given places:
here is a sample of my code :
cartSchema.methods.getLocation = function (destinations, origins) {
let result = {};
try {
distance.matrix(origins, destinations, function (err, distances) {
if (!err) result = distances;
});
} catch (e) {
res.status(500).json({ message: e.message });
}
console.log(result);
return result;
};
as you can see here I want to return the distances where I have passed its value to the result but it still not return undefined.
Thanks in advance
USE PROMISE
The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
in you case you need something like this:
cartSchema.methods.getLocation = function (destinations, origins) {
return new Promise((resolve) => {
try {
distance.matrix(origins, destinations, function (err, distances) {
if (!err) result = distances;
...
resolve(result);
});
} catch (e) {
res.status(500).json({ message: e.message });
}
}
};
/// access to the result
cartSchema.methods.getLocation().then(result=>{console.log(result);})
I see, you can solve this with promises or callback functions. Here is a callback example. It cannot return the result without promises. Instead, give it a function to call (successCallback) when it gets the result.
cartSchema.methods.getLocation = function (destinations, origins, successCallback, errorCallback) {
try {
distance.matrix(origins, destinations, function (err, distances) {
if (!err) successCallback(distances)
else {
errorCallback(err);
}
});
} catch (e) {
errorCallback(e);
}
};
cartSchema.methods.getLocation({}, {}, function(distances){
//do something with distances here
}, console.err)

javascript promise all array of values passed as argument

Given the following array of values:
var sportList = ['football', 'volleyball'];
i want to run a query on mongo database using each of these values:
function myFunc(sport, callback) {
mongoDB.sports.find({'name': sport}, function (error, result) {
if (error) {
callback(error)
} else {
callback(null, result)
}
})
}
so i build my promises like:
var promises = sportList.map(function(val){
return myFunc(val);
});
and then trying to run all in a promise all chain:
Promise.all(promises)
.then(function (result) {
console.log('log results: ', result);
})
.catch(function (error) {
console.log(error);
});
but this is not working, because it is complaining that the callback is undefined, how can i fix this up correctly?
The reason for the error is that you are calling the myFunc method without supplying the callback parameter.
A solution would be to replace the myFunc function with the below. This function will return a new Promise. I haven't tested the below code but it should work.
function myFunc(sport) {
return new Promise((resolve, reject) => {
mongoDB.sports.find({'name': sport}, function (error, result) {
if (error) {
reject(error);
} else {
resolve(result);
}
})
}));
}

Javascript Promise undefined

I am new to Javascript and AngularJS, I am trying to figure this out.
I made an angular service that execute DB queries and return promise.
executeStatement = function(db, sql, values, onsuccess, onerror) {
if (!!db.executeSql) {
return db.executeSql(sql, values || [], onsuccess, onerror);
} else {
return db.transaction(function(tx) {
return tx.executeSql(sql, values, function(ignored, rs) {
return onsuccess(rs);
}, function(ignored, error) {
return onerror(error);
});
});
}
};
this.executeStatement = function(sql, values) {
$ionicPlatform.ready( function() {
return new Promise(function(resolve, reject) {
return executeStatement(myDB, sql, values, resolve, reject);
});
} );
}
And then If I call the executeStatement like this in the angular service module.
this.extract = function(callback) {
_DB.executeStatement('SELECT * FROM FRIDGE', []).then(callback);}
Shouldn't this return a promise after the functions are finished running?
I'm getting undefined :(
Some help would be appreciated!
The this.executeStatement() function needs to return the result of $ionicPlatform.ready():
this.executeStatement = function(sql, values) {
return $ionicPlatform.ready( function() {
return new Promise(function(resolve, reject) {
return executeStatement(myDB, sql, values, resolve, reject);
});
} );
}
Now you can access whatever's returned from executeStatement in your callback, which you can pass in as the argument to the .then() function:
_DB.executeStatement('SELECT * FROM FRIDGE', []).then(callback);
The functions within executeStatement are not Promise, do not need to be returned, where onFulfilled, onRejected of Promise constructor is passed as parameters to a function, if and when onsuccess, onerror are called, the original Promise will be resolved or rejected.
Include second parameter to chained .then() or use .catch() to handle potential errors within Promise chain.
Not sure if $ionicPlatform.ready returns a Promise?
_executeStatement = function(db, sql, values, onsuccess, onerror) {
if (!!db.executeSql) {
// `onsuccess` or `onerror` need to be called for `Promise`
// to be fullfiled; a value needs to be passed to
// `onsuccess` or `onerror` to get the value at `.then()` or `.catch()`
db.executeSql(sql, values || [], onsuccess, onerror);
} else {
db.transaction(function(tx) {
tx.executeSql(sql, values, function(ignored, rs) {
onsuccess(rs);
}, function(ignored, error) {
onerror(error);
});
});
}
};
this.executeStatement = function(sql, values) {
return $ionicPlatform.ready( function() {
return new Promise(function(resolve, reject) {
_executeStatement(myDB, sql, values, resolve, reject);
})
.catch(function(err) {
// handle, pass error here
console.log(err);
return err
})
});
}
this.executeStatement(/* parameters */)
.then(function success(data) {
console.log(data);
}, function err(err) {
console.log(err);
});

Abstract function in order to let choose to return promises or callback

I don't know maybe it's an antipattern.
Soon very young developers will join our developer team, and I would like to let them choose if they want to use the module with callback or Promises pattern.
This function basically save data into the database. I repeat the db.insert flow in order to abstract the function, but is there an other way to do this?
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);
});
});
}
}
I like the bluebird .asCallback(...) approach:
function somethingAsync(cb) {
return somePromise().asCallback(cb);
}
...essentially, you return a promise and call a callback (if one was passed). Therefore, it can be used either way. If you don't want to adopt Bluebird, you can essentially do the same thing like this:
function somethingAsync(cb) {
var promise = somePromise();
if (!cb) return promise;
promise.then(res => cb(null, res), err => cb(err));
}
You can just implement the callback and then use the pify module to add the promise.
You could just implement the normal CPS (continuation passing style) function and include a generic promisify function that adapts cps functions to promise-returning functions.
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)
})
})
}
}
You can use it with the continuation like this
create (data, function(err, res) {
if (err)
// do something with the error
else
// do something with the result
})
Or you can use promises like this
promisify(create)(data)
.then(res => {
// do something with the result
})
.catch(err => {
// do something with the error
})
You'll notice that the create function is pretty redundant tho. There's really no need to wrap the db.insert like this. Instead, skip creating the create function and just use both like this
// for cps, use normal api
db.insert(data, function(err, res) { ... })
// for promises, use the wrapper
promisify(db.insert)(data).then( ... )

How do I chain nested promises with Q? I can't get them to run in proper order

I want to be able to chain together methods which themselves may include chained methods.
The log should read "first, second, third". However, in practice it comes out "second, third, first".
I know this code is a bit redundant, but I'm just trying to understand how promises/node executes. How would I write promise-based functions that themselves can be chained together?
user.increaseReadings(id)
.then(function(val) { console.log("second",val); return user.findById(id); })
.then(function(val) { console.log("third",val); res.json(val); });
}
From /models/user module:
exports.findById = findById;
function findById(id) {
deferred = Q.defer();
User.findById(id, function(err, doc) {
if (err) return deferred.reject(err);
deferred.resolve(doc);
});
return deferred.promise;
}
exports.increaseReadings = increaseReadings;
function increaseReadings(id) {
deferred = Q.defer();
findById(id).then(function(doc) { <-- here's the problem
doc.readings++;
doc.save(function(err, doc) {
console.log("first");
if (err) return deferred.reject(err);
deferred.resolve(doc);
});
});
return deferred.promise;
}
You could rewrite your increaseReadings as such:
function increaseReadings(id) {
return findById(id).then(function(doc) {
console.log(doc);
var deferred = Q.defer();
doc.readings++;
doc.save(function(err, doc) {
console.log("first");
if (err) return deferred.reject(err);
deferred.resolve(doc);
});
return deferred.promise;
});
}
The important difference between this code and the one you wrote is that the anonymous function passed to the 'then' method returns a promise.
In most promise implementations, if you return a promise as a result of a handler, the next step in the chain will not execute until you resolve that promise you returned.

Categories