How to create javascript promise chain with array function? - javascript

I am facing a weired issue when creating a js promise chain.In promise,when I am using array function with (),I don'nt get the expected value.It give me the 'undefined' value in second then.
Here is the js code:
let x = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('sonet970#gmail.com');
}, 2000);
});
function y(email) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(email);
}, 4000);
});
}
x.then((res) => {
y(res);
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
But when I didn't use the ()=>{} syntax inside the .then,I got the expected answer.
Here is the example of wright code:
let x = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('sonet970#gmail.com');
}, 2000);
});
function y(email) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(email);
}, 4000);
});
}
x.then((res) => y(res))
.then((res) => console.log(res))
.catch((err) => console.log(err));
Can anyone please help me with this issue?

In order to chain promises you need to return Promise.
This sample works correctly
x.then((res) => y(res))
.then((res) => console.log(res))
.catch((err) => console.log(err));
because (res) => y(res) means:
(res) => {
return y(res)
}
and the result of y() promise is passed to the next .then
So to solve your code you need to write it in this way:
x.then((res) => {
// do some calculations
return y(res);
})
.then((res) => {
// result of y promise
console.log(res);
})
.catch((err) => {
console.log(err);
});

Returning something from a function using curly braces {} means that you need to use keyword return to return something:
x.then((res) => {
return y(res);
});
Using arrow functions, if no curly braces added, the immediately value after => is returned.
then((res) => console.log(res));

Thank you all for your answers.Now I understand,why my first code din't work.It all about array function,nothing w
ith promises!

Related

confused with .then() in promises

I'm new to js and I'm learning promises. I came up with this code which will print the resolved values from every function and will call new functions using .then
function login() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({username : 'default'})
}, 1000)
})
}
function getVideos() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(['vid1', 'vid2'])
},1000)
})
}
function getDesc() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('desc')
}, 1000)
})
}
const test = login()
test.then(res => {
console.log(res)
getVideos()
})
.then(res => {
console.log(res)
getDesc()
})
.then(res => console.log(res))
But, I'm not getting the expected result, I thought all the statements in .then() needed to be executed and resolved to continue to the next .then() statement. But clearly this is not the case here as I'm getting the following as the output -
{ username: 'default' }
undefined
undefined
But I expected the output to be similar to this -
{username : 'default}
['vid1', 'vid2']
desc
pls, point where I'm going wrong here. Any help is appreciated, thanks a lot
You need to add return to inside your chains when you're calling those functions. For example:
function login() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({username : 'default'})
}, 1000)
})
}
function getVideos() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(['vid1', 'vid2'])
},1000)
})
}
function getDesc() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('desc')
}, 1000)
})
}
const test = login()
test.then(res => {
console.log(res)
return getVideos()
})
.then(res => {
console.log(res)
return getDesc()
})
.then(res => console.log(res))
This is a good guide: https://javascript.info/promise-chaining
Make a couple of very minor changes:
const test = login()
test.then(res => {
console.log(res)
return getVideos()
})
.then(res => {
console.log(res)
return getDesc()
})
.then(res => console.log(res))
To chain promises together, you need to return the promises at each step. As it is you're implicitly returning undefined which is not a promise.

Traditional way of doing asnyc method in javascript

I was searching online on how we create the traditional way of doing async function in Javascript but it wasn't available. I have implemented a promise function in my program, however the software that I am using (tableu) to create all custom styling does not support ES5-ES8 and async functions, as this will throw an error, so I was wondering if this is possible.
function promise() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), 500);
})
}
async function result() {
await promise();
}
result().then(render => {
customStyle()
});
All of my code shown is working fine. I'm wondering how can I convert this to the old way of doing async functions. Is this possible or is it only available in ES8?
Callbacks are the non-Promise or async/await way of doing this, and are basically how those things work under the hood.
Here's a simple example by modifying your snippet:
function promise(callback) {
setTimeout(() => callback(), 500);
}
function result() {
promise(callback);
}
function callback() {
customStyle();
};
Instead of result being an async function that you can await elsewhere in your code, it could also take a callback argument, like promise, that you would pass it when it's invoked. The implementation of that callback function would be like the then of an actual Promise.
Now you can see why the Promise API and async/await were such nice improvements to the spec.
To use promises the tradicional way, you have to replace the await and use .then(()=> ...). I'll try to show a snippet here to help you to understood.
The code that you have shown does not need the async or await, it goes well like that
function promise() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('resolved')
resolve()
}, 500);
})
}
promise().then(render => {
customStyle()
});
Here i'll show you a code that have a good use of it and then I'll convert it:
function callSomeService() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('service whas called')
resolve({ idOfSomething: 1 })
}, 2000);
})
}
function callAnotherServiceUsingTheDataOfThePreviousCall(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('service whas called with', data)
resolve(['potato 1', 'potato 2', 'potato 3'])
}, 2000);
})
}
async function result() {
const serviceResponse = await callSomeService();
const arrayOfPotatos = await callAnotherServiceUsingTheDataOfThePreviousCall(serviceResponse);
return arrayOfPotatos.map((potato, index) => `${index} - ${potato}`)
}
result().then(arrayOfPotatos => {
arrayOfPotatos.forEach(potato => console.log(potato))
});
Now I'll convert it to not use async or await, but still using promises.
function callSomeService() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('service whas called')
resolve({ idOfSomething: 1 })
}, 2000)
})
}
function callAnotherServiceUsingTheDataOfThePreviousCall(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('service whas called with', data)
resolve(['potato 1', 'potato 2', 'potato 3'])
}, 2000)
})
}
function result() {
return callSomeService().then(serviceResponse => {
return callAnotherServiceUsingTheDataOfThePreviousCall(
serviceResponse
).then(arrayOfPotatos => {
return arrayOfPotatos.map((potato, index) => `${index} - ${potato}`)
})
})
}
result().then(arrayOfPotatos => {
arrayOfPotatos.forEach(potato => console.log(potato))
})
Those two last codes does the same thing, but the second use async and await and the third does not. Async and await are just a syntax sugar to use promises.
I expect that will help you.

Node.js Promise with mongoose

I have difficulty using Promise.
I want to get data from one more tables in mongodb.
but I fell in callback hell, So I tried to solve this but I couldn't.
What should I do? the result came out 'undefined'.
Many Thanks,
let mongoose = require('mongoose');
mongoose.Promise = global.Promise;
....
exports.Recommend = (id) => {
User.find({User_id: myId})
.then((result) => {
return Promise.resolve(result[0].age)
}).then(age => {
return new Promise((resolve,rejject)=>{
resolve(User.find()
.select('User_id')
.where('age').equals(age))
})
}).then((Users_id) => {
Users_id.forEach((user, idx, arr) => {
Count.find()
.select('board_id')
.where('User_id').equals(user.User_id)
.exec((err, items) => {
return new Promise((resolve,reject)=>{
resolve(
items.forEach((post, idx, arr) => {
posts.push(post.board_id)
}))
})
})
})
}).then(()=>{
console.log("posts:"+posts);
})
}
Avoid Promise.resolve, avoid using the new Promise constructor like Promise.resolve, avoid the Promise constructor antipattern, and avoid forEach, and don't forget to return the promise chain from your function:
exports.Recommend = (id) => {
return User.find({User_id: myId}).then(result => {
return User.find()
.select('User_id')
.where('age')
.equals(result[0].age));
}).then(user_ids => {
return Promise.all(user_ids.map((user, idx, arr) => {
return Count.find()
.select('board_id')
.where('User_id').equals(user.User_id)
.exec()
.then(posts => posts.map(post => post.board_id));
}));
}).then(board_ids => {
console.log("posts:"+board_ids);
})
}
You have the problem with 3rd .then, I would like to recommend you to use Promise.all function to run the parallel database query. Following example may help you
exports.Recommend = (id) => {
User.find({
User_id: myId
})
.then((result) => {
return User.find()
.select('User_id')
.where('age').equals(result[0].age)
}).then((Users_id) => {
return Promise.all(Users_id.map((user, idx, arr) => {
return Count.find()
.select('board_id')
.where('User_id').equals(user.User_id)
}));
}).then((Users_id) => {
Users_id.forEach(items => {
items.forEach(post => {
posts.push(post.board_id)
})
})
}).then(() => {
console.log("posts:" + posts);
})
}

Promise return multiple values

I use the following code to return promise which is working OK.
The promise return the data value
run: () => {
return new Promise((resolve, reject) => {
....
}).then((data) => {
let loginApi = data[0]
let test = 1;
}).catch((err) => {
if (err.statusCode === 302) {
var data = url.parse(err.response.headers.location, true)
resolve(data )
}
})
});
I call it
module.run()
.then((data) => {
And I was able to get the data.
now I want to return also value test in the resolve, how should I do it?
I try to add it like this
resolve({data,test});
resolve([data,test]);
with call like
module.run()
.then({data,test}) => {
without success(test is empty), I read about spread but this is the only option?
I use ES6 with bluebird latest version
If you are using promise chain, in promise chain you have then->then->catch->... format. Always return Promise.resolve or Promise.reject. Promise.resolve will give success result for next then block and Promise.reject will go to next catch block.
var module = {
run: () => {
return new Promise((resolve, reject) => {
// ....
resolve('promise resolved')
}).then((data) => {
let loginApi = data[0]
let test = 1;
return Promise.resolve({data,test})
}).catch((err) => {
if (err.statusCode === 302) {
var data = url.parse(err.response.headers.location, true)
return Promise.resolve({data, test});
}
return Promise.reject(err);
})
}
};
module.run().then(({data, test}) => {
console.log(data, test);
})

Catching promise errors from a loop

I need to call multiple promises inside a for loop, but it gives me unhandled promise exception during each run. The way to solve this is to return the second promise, this way the last catch would be executed and it would work without errors, but - second and more iterations would not be executed.
const doFirstThing = () => {
return new Promise((resolve, reject) => {
setTimeout(() => (resolve(['a', 'b', 'c'])), 1000);
});
}
const doSecondThing = () => {
return new Promise((resolve, reject) => {
setTimeout(() => (reject('test')), 500); // reject here
});
}
doFirstThing()
.then(results => {
results.forEach(result => {
doSecondThing(result)
.then(() => console.log(result, 'done'));
});
})
.catch(error => console.log(error));
How can I deal with this?
To prevent unhandled promise exception chain .catch() to lat .then(); substitute using Promise.all() and .map() for .forEach()
const doFirstThing = () => {
return new Promise((resolve, reject) => {
setTimeout(() => (resolve(['a', 'b', 'c'])), 1000);
})
}
const doSecondThing = (r) => {
return new Promise((resolve, reject) => {
setTimeout(() => (reject('test')), 500); // reject here
})
}
doFirstThing()
.then(results => {
return Promise.all(results.map(result => {
return doSecondThing(result)
}));
})
.then((result) => console.log(result, 'done'))
.catch(error => console.log(`err:${error}`));

Categories