JavaScript Promise wrapped in function or bare? - javascript

If I'm calling a function that is a promise, do I need to do this "wrap it in another function" layer?
Promise
.resolve()
.then(()=>{ // this part seems excessive
return new Promise(resolve={
// my function's guts
Can I return the new promise directly, like
Promise
.resolve()
.then(new Promise(resolve={
// my function's guts

If I'm calling a function that is a promise, do I need to do this
"wrap it in another function" layer?
Yes otherwise it'll be executed immediately I recommend you create your promises within a named function that way it allows you to keep your chain neat and readable and code more reusable.
myTask1()
.then(myTask2)
.then(myTask3);
function myTask1() {
return new Promise((resolve, reject) => {
console.log("Task 1");
resolve("Task 1");
})
}
function myTask2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Task 2");
resolve("Task 2");
}, 1000)
})
}
function myTask3() {
return new Promise((resolve, reject) => {
console.log("Task 3");
resolve("Task 3");
})
}
Can I return the new promise directly, like.... .then(new Promise(resolve={?
No there's one critical difference with instantiating the promise like that. When you wrap the promise in a function it isn't evaluated until the previous promise completes whereas if you instantiate it inline then it's evaluated immediately which may cause unexpected results:
new Promise((resolve, reject) => {
resolve()
})
.then(new Promise((resolve, reject) => {
console.log("Task 1");
}))
.then(new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Task 2");
resolve("Task 2");
}, 1000);
}))
.then(new Promise((resolve, reject) => {
console.log("Task 3");
resolve("Task 3");
}))
To make the above work you could change it so that the closure returns a promise, but it starts to look pretty messy:
new Promise((resolve, reject) => {
resolve()
})
.then(() => {
return new Promise((resolve, reject) => {
console.log("Task 1");
resolve("Task 1");
})
})
.then(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Task 2");
resolve("Task 2");
}, 1000);
});
})
.then(() => {
return new Promise((resolve, reject) => {
console.log("Task 3");
resolve("Task 3");
});
})

You do have to wrap the promise in another function.
However, you can shorten it a bit because:
() => {
return new Promise()
}
is the same as
() => new Promise()
So you could do something like this:
Promise
.resolve()
.then(() => new Promise(resolve => {
// your function's guts

There is no need to use Promise.resolve() when creating a new promise.
The usual way to create a promise is to make a function that returns the promise:
function myFunc() {
return new Promise((resolve, reject) => {
// your async logic here
});
}
Then, you call it like this:
myFunc().then(result => {
// code that uses async result here
});
And, you have put your promise creation logic into a reusable function.
It is possible (though usually less practical) to create a new promise without putting it in a containing function. For example, you can do this:
new Promise((resolve, reject) => {
// async logic here that eventually calls resolve or reject
}).then(result => {
// process async result here
}).catch(err => {
// process error here
});

The handler for then could simply return a value.
Promise.resolve('value').then(() => 'otherValue');

Related

Put Javascript Promise into Functions

I have two promises that I am resolving with promise.all:
var mictest1 = new Promise((resolve, reject) => {
resolve(true);
});
var mictest2 = new Promise((resolve, reject) => {
resolve(true);
});
Promise.all([mictest1, mictest2]).then(data => {
console.log("test passed: " + data);
})
I would like to put the promises mictest1 and mictest2 into a function called mictest() so it does the following:
mictest();
Promise.all([mictest1, mictest2]).then(data => {
console.log("test passed: " + data);
})
In this way I can call the function at will, and when the promises get complicated, i don't have that block of text in front of promise.all
Maybe you're looking for the mictest function to return the Promise.all?
const mictest = () => {
var mictest1 = new Promise((resolve, reject) => {
resolve(true);
});
var mictest2 = new Promise((resolve, reject) => {
resolve(true);
});
return Promise.all([mictest1, mictest2]);
};
mictest().then((data) => {
console.log('test passed:', data);
});
I think you are looking for a function that returns the promise:
function mictest() {
return new Promise((resolve, reject) => {
resolve(true);
});
}
You'd use it like
var mictest1 = mictest();
var mictest2 = mictest();
Promise.all([mictest1, mictest2]).then(data => {
console.log("test passed: " + data);
})
or simply
Promise.all([mictest(), mictest()]).then(data => {
console.log("test passed: " + data);
})
Not quite the way you imagined it but you can get very close:
let promises = mictest();
Promise.all(promises).then(data => {
console.log("test passed: " + data);
})
That's just changing two lines of your imagined code. The implementation is simple:
function mictest () {
return [
new Promise((resolve, reject) => {
resolve(true);
}),
new Promise((resolve, reject) => {
resolve(true);
})
]
}
A promise is a value just like strings, numbers, arrays etc. You can treat it like any value. It just happens to be an object that has a .then() method and is awaitable
Note: actually, any object with a .then() method is awaitable even your own custom created non-promise object (actually any object with a .then() method is a promise even though it is not a Promise)

Unable to retrieve data from a promise

I am unable to retrieve data from a promise using then(). Where am I going wrong?
async function A(){
await new Promise((resolve, reject) => setTimeout(()=>{},1000));
return 45;
}
A().then(data => console.log(data))
I'm running this code with nodejs.
I expect the output to print 45. But the program just executes for 1 second and doesn't print anything.
If I remove the timeout statement, I am able to print 45.
Where am I going wrong?
You need to resolve your promise and then return can run.
async function A() {
await new Promise((resolve, reject) => setTimeout(() => resolve(), 1000));
return 45;
}
A().then(data => console.log(data))
You could also return promise from A function and then use async/await.
function A() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(45), 1000)
})
}
(async() => {
const res = await A();
console.log(res)
})()
Your function A should return a promise.
function A() {
return new Promise((resolve, reject) => setTimeout(() => resolve('hello'), 1000));
}
A().then(data => console.log(data))
Function A should return a promise and use async/await along with IFI (Immediate Function Invocation method)
function A(){
return new Promise((resolve, reject) => setTimeout(()=>{resolve(100)},1000));
}
(async () => {
var data = await A()
console.log(data)
})();

How to chain promises

In this simplified example, I am calling three functions when the first promise gets resolved.
var test = new Promise(function (res, err) { setTimeout(res, 3000) })
test.then( () => { console.log("A") });
test.then( () => {
return new Promise(function(res, err) {
setTimeout(()=> { console.log("C");
res() }, 3000)
});
});
test.then( () => { console.log("B") });
The output as expected is A B C.
Let's suppose that I want to invoke the third .then to console B only when the second promise gets resolved.
If I try to store the second promise (myProm) in global and attach a .then function on it, I'll get (reasonably) a TypeError because at compile time myProm is still undefined.
var test = new Promise(function (res, err) { setTimeout(res, 3000) })
var myProm;
test.then( () => { console.log("A") });
test.then( () => {
myProm = new Promise(function(res, err) {
setTimeout(()=> { console.log("C");
res() }, 3000)
})
return myProm;
});
myProm.then( () => { console.log("B") });
How do I proceed? What's the best way to chain two promises together so that the returned Promise obj from one .then needs to get resolved before we can execute the next then.
In this scenario, the output I'd like to have would be A C B
then returns a promise that resolves when the indicated function has run and the value it returned has resolved (this is a slight oversimplification, but sufficient for the task here).
Therefore, to chain a promise on the result of a then. Just tack on another .then:
var test = new Promise(function (res, err) { setTimeout(res, 3000) })
test.then( () => { console.log("A") });
test
.then( () => {
return new Promise(function(res, err) {
setTimeout(()=> { console.log("C"); res() }, 3000);
});
})
.then( () => { console.log("B") });
Each time you call .then, you create a new Promise that resolves when the Promise returned by that .then resolves. You should assign the result of the myProm-containing .then to a variable, and then call .then on that variable:
var test = new Promise(function (res, err) { setTimeout(res, 500) })
var myProm;
test.then( () => { console.log("A") })
.then( () => {
myProm = new Promise(function(res, err) {
setTimeout(()=> { console.log("C");
res() }, 500)
})
return myProm;
})
.then( () => { console.log("B") });
Most of the time when using Promises, you should be chaining .thens like this. Only do prom.then(...) ... prom.then(...) when you want to initialize two completely separate asynchronous operations when the prom resolves.

Promise - `then()` not works as expect

I do have 2 function. I am chaining with then() method for promise. But I am trying to initiate the second function after the first promise happend. But now the second function call as first. how to fix this?
or any issue with my code?
here is my try:
var getData = function(){
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(42); //consoles as second
}, 5000);
})
}
var getDataMoreData = function(){
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(43); //consoles as first
}, 3000);
})
}
getData().then((data)=> console.log('Data', data)).then(getDataMoreData().then((data)=> console.log('data--', data )));
Live Demo
.then accepts a function as a parameter. When you do
.then(getDataMoreData()
.then((data) => console.log('data--', data))
);
, it immediately calls getDataMoreData() (with the expectation that it will return a function that it can put into the promise chain). But getDataMoreData does not return a function - it returns a promise.
Any function calls immediately within a then get executed immediately, as it attempts to build the .then promise chain. Simply list the function variable inside the then instead of calling it:
var getData = function() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(42);
}, 500);
})
}
var getDataMoreData = function() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(43);
}, 300);
})
}
getData()
.then((data) => console.log('Data', data))
.then(getDataMoreData)
.then((data) => console.log('data--', data));

Nested Promises, And Another After Completion [duplicate]

I have a situation where I think the only choice for me is to nest some Promises within each other. I have a Promise that needs to be performed and a method that does something until that Promise is complete. Something like this:
let promise = new Promise((resolve, reject) => {
// Do some stuff
});
doSomethingUntilPromiseisDone(promise);
However, within my Promise, I need to execute another method that returns another Promise:
let promise = new Promise((resolve, reject) => {
fetchValue(url)
.then((value) => {
// Do something here
}).catch((err) => {
console.error(err);
});
});
doSomethingUntilPromiseisDone(promise);
But now, in the fetchValue method's then statement, I have another method I need to execute that, guess what, returns another Promise:
let promise = new Promise((resolve, reject) => {
fetchValue(url)
.then((value) => {
saveToCache(value)
.then((success) => {
console.log('success!!');
resolve('success');
});
}).catch((err) => {
console.error(err);
});
});
doSomethingUntilPromiseisDone(promise);
So in the end, I have a Promise, within a Promise, within a Promise. Is there someway I can structure this better so that it is more straightforward? It seems like nesting them within each other is counter to Promise's intended chaining approach.
Use .then()
let doStuff = (resolve, reject) => {/* resolve() or reject() */};
let promise = new Promise(doStuff);
doSomethingUntilPromiseisDone(
promise
.then(value => fetchValue(url))
.then(value => value.blob())
.then(saveToCache)
)
.then(success => console.log("success!!"))
.catch(err => console.error(err))
you can use generator to flatten your nested promises (Bluebird.couroutine or Generators)
//Bluebird.couroutine
const generator = Promise.coroutine(function*() {
try {
const value = yield fetchValue(url);
const success = yield saveToCache(value);
console.log('success:', success);
} catch(e) {
console.error(err);
}
}));
generator();
Each function will call the next one with the result of the method before.
var promises = [1,2,3].map((guid)=>{
return (param)=> {
console.log("param", param);
var id = guid;
return new Promise(resolve => {
// resolve in a random amount of time
setTimeout(function () {
resolve(id);
}, (Math.random() * 1.5 | 0) * 1000);
});
}
}).reduce(function (acc, curr, index) {
return acc.then(function (res) {
return curr(res[index-1]).then(function (result) {
console.log("result", result);
res.push(result);
return res;
});
});
}, Promise.resolve([]));
promises.then(console.log);

Categories

Resources