javascript promise all array of values passed as argument - javascript

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);
}
})
}));
}

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)

How to handle reject promise error in outer try catch with inner Promise.all?

When an error/rejection occurs in detectingDog or detectingDog, the error is successfully handled by the .catch(error of the Promise.all() but I want the error to be directly handled by the catch (err) of the try structure.
How can I do this ?
PS: I have already tried to get rid of the .catch(error but then the Promise.all() hangs forever
try {
function detectingDog(bufferedData) {
return new Promise((resolve, reject) => {
package.detectDog(bufferedData, function(error, data) {
if (error) {
reject(error);
} else {
return resolve(data);
}
});
});
}
function detectingCat(bufferedData) {
return new Promise((resolve, reject) => {
package.detectCat(bufferedData, function(error, data) {
if (error) {
reject(error);
} else {
return resolve(data);
}
});
});
}
Promise.all([
detectingDog(param1),
detectingCat(param2)
]).then(responseData => {
callback(undefined, responseData);
}).catch(error => {
// (1) I need to pass the error to the outer structure where error handling is done
});
} catch (err) {
console.log(err);
// handing of the inner error (2) here
callback(err);
}
Thanks!
...but I want the error to be directly handled by the catch (err) of the try structure.
You can't do that in a non-async function, because control has already left the try/catch by the time that rejection occurs, which is after whatever function this code is in (if any) has returned.
In an async function, you can use await on a promise, which will make a rejection throw, so it would go to your try/catch. So you could do the following, but keep reading because it's fairly odd:
// In an `async` function
try {
function detectingDog(bufferedData) {
return new Promise((resolve, reject) => {
package.detectDog(bufferedData, function(error, data) {
if (error) {
reject(error);
} else {
return resolve(data);
}
});
});
}
function detectingCat(bufferedData) {
return new Promise((resolve, reject) => {
package.detectCat(bufferedData, function(error, data) {
if (error) {
reject(error);
} else {
return resolve(data);
}
});
});
}
const responseData = await Promise.all([
detectingDog(param1),
detectingCat(param2)
]);
callback(responseData);
} catch (err) {
console.log(err);
callback(err);
}
...but it doesn't make a lot of sense to go to the trouble of converting callback APIs to promises if you're just going to provide a callback-based API to your caller. Just return a promise. That makes the whole try/catch disappear:
// No need for these to be nested
function detectingDog(bufferedData) {
return new Promise((resolve, reject) => {
package.detectDog(bufferedData, function(error, data) {
if (error) {
reject(error);
} else {
resolve(data); // No need for `return`
}
});
});
}
function detectingCat(bufferedData) {
return new Promise((resolve, reject) => {
package.detectCat(bufferedData, function(error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
});
}
function example(param1, param2) {
return Promise.all([
detectingDog(param1),
detectingCat(param2)
]);
}
You have two options here.
If you really need the try/catch block you will need to run your code in an async function, leveraging the fact that awaiting a rejected Promise will throw an error in this context:
(async function () { // you might not need the immediately invoking function wrapper depending on your context
try {
function one(bufferedData) {
// return a promise
}
function two(bufferedData) {
// return a Promise
}
const responseData = await Promise.all([
one(param1),
two(param2)
])
callback(undefined, responseData)
} catch (err) {
console.log(err);
// handing of the inner error (2) here
callback(err)
}
})()
Alternatively, you can also just handle the error in the catch block of your Promise chain:
function one(bufferedData) {
// return a promise
}
function two(bufferedData) {
// return a Promise
}
Promise.all([
one(param1),
two(param2)
])
.then((responseData) => {
callback(undefined, responseData)
})
.catch((err) => {
console.log(err);
// handing of the inner error (2) here
callback(err)
})

JavaScript testing promise

I'm trying to test a function which recives a promise like this
{
state: 'fulfilled'
value:[Array]
}
function register (foo) {
return new Promise((resolve,reject)=>{
query = "INSERT IGNORE INTO....";
connection.query(query, [foo.value.from, foo.value.id], (err, res, fields) => {
if(err){
return undefined //this will change
}
return foo
})
})
}
The thing is I am returning, non rejecting neither resolving. So when Im testing..
it('insertion error', function () {
var res = 'error'
connection = {
query: (query, input, cb) =>{
return cb(res, null, null)
}
}
let database = proxyquire('path/to',{
'./connection': connection
})
var input =
{
value: {
id: 'bar',
data: [],
from: 'foo'
}}
return database.register(input)
.then( (result) => {
expect(result).to.be.undefined
})
.catch( (err) => {
console.log(err)
err = new Error (`Test fail: ${err}`)
throw err;
})
})
The function works well, Im pretty sure of that.
The other thing I'm sure of is that the THEN/CATCH condition never shows up. I know if I replace the return for resolve it will show up, but I need to be returned.
What should I modify, or how should I test it.
This is a basic example how can you make a promisse, in this example you can send true or false in the register() function.
function register ( foo ) {
return new Promise( (resolve, reject) =>{
if(foo){
resolve('Done');
}else{
reject('Error')
}
} )
}
register(false).then( result=>{
document.write('promisse success... ', result);
} ).catch( error => {
document.write('promisse error... ', error);
} )

How to wrap a callback function in a Parse.Promise

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
});

Correctly chaining Promises

I want to bind promises sequentially, inside a loop. I need this to user accounts, where the result of one operation depends on another.
I am trying to write a flat version - all code in one place, using bind. That's at least what I wanted. I wrapped promises around two create methods, as below:
function create(myApi, record) {
return new Promise(function (resolve, reject) {
myApi.create(record, function (err, result) {
if (err) reject(err);
else resolve(result);
});
});
}
function createUser(myApi, record) {
return new Promise(function (resolve, reject) {
myApi.createUser(record, function (err, result) {
if (err) reject(err);
else resolve(result);
});
});
}
Now, I want to create users in a loop as:
for ( var i = 0; i < dummyData.accounts.length; i++) {
var cursorUser = dummyData.accounts[i];
var auth0User = {
email: cursorUser.email,
password: cursorUser.password,
connection: 'Username-Password-Authentication'
};
createUser(api, auth0User)
.then( function(auth0Info) {
console.log("Auth0 userInfo: ", auth0Info);
cursorUser.authProfile = auth0Info;
create(accountsAPIService, cursorUser)
.then(function (account) {
console.log("created account:", account);
})
.catch(function (err) {
console.log('count not create account for user, error: ', err, '\nfor: ', auth0User);
});
})
.catch(function (err) {
console.log('could not create auth0 user, error: ', err, '\nfor: ', auth0User);
});
}
Since the two method are asynchronous, it is of course not working correctly. Calls are not executed sequentially. I want to chain promises so that create does not run until a call from createUser returned. Tried using bind, but it did not work for me. It is how one should do the sequential chaining? I bind on .then of the createUser? Please advise.
When you return a promise from a then, the then chained after will resolve/reject with that promise instead of the original promise.
createUser(api, auth0User).then(function(auth0Info) {
cursorUser.authProfile = auth0Info;
// Return create's promise
return create(accountsAPIService, cursorUser);
}, function (err) {
console.log('could not create auth0 user, error: ', err, '\nfor: ', auth0User);
})
// This will wait for create's promise instead of createUser's promise
.then(function (account) {
console.log("created account:", account);
}, function (err) {
console.log('count not create account for user, error: ', err, '\nfor: ', auth0User);
})
Using ES6 you can use generators which allows you to do write async task as they were async. In this example i am using bluebird but ofc there are others great valid options.
var CreateUserGenerator = BPromise.coroutine(function * (arg) {
for ( var i = 0; i < dummyData.accounts.length; i++) {
var cursorUser = dummyData.accounts[i];
var auth0User = {
email: cursorUser.email,
password: cursorUser.password,
connection: 'Username-Password-Authentication'
};
var auth0Info = yield createUser(api, auth0User);
console.log("Auth0 userInfo: ", auth0Info);
cursorUser.authProfile = auth0Info;
var account = yield create(accountsAPIService, cursorUser)
console.log("created account:", account);
}
}
function generateorWithCatch (argument) {
creatLoopUser(arg)
.catch(function (err) {
console.log('could not create auth0 user, error: ', err, '\nfor: ', auth0User);
});
}
In this solution i assume your create and createUser functions are written and return value correctly

Categories