Reputation: 138
I want do a sync task and have tried something like the code bellow, It isn't same what I thought about the Promise before, can you explain this one for me?
var p2 = new Promise((resolve, reject) => {
console.log('Promise 2');
resolve();
});
var p1 = new Promise((resolve, reject) => {
console.log('Promise 1');
resolve();
});
Promise.all([p1]).then(p2);
It always output the "Promise 2" before "Promise 1".
Upvotes: 3
Views: 96
Reputation: 135396
I just want to show you that you would have output even if you never used Promise.all
or .then
-
const makePromise = x =>
new Promise(r =>
( console.log("constructing...", x)
, setTimeout(r, 2000, x) // fake 2 second delay
)
)
const a = makePromise("a")
const b = makePromise("b")
const c = makePromise("c")
console.log("construction complete!")
// constructing... "a"
// constructing... "b"
// constructing... "c"
// construction complete!
Above, we construct three (3) promises and output is displayed even though we never used a
, b
, or c
anywhere else in the program.
When we attach .then(handler)
the resolved values are passed to handler
-
const makePromise = x =>
new Promise(r =>
( console.log("constructing...", x)
, setTimeout(r, 2000, x)
)
)
const a = makePromise("a")
const b = makePromise("b")
const c = makePromise("c")
console.log("construction complete!")
// constructing... "a"
// constructing... "b"
// constructing... "c"
// construction complete!
Promise.all([a, b, c])
.then(r => console.log("done!", r))
.catch(e => console.error("error!", e))
// done!
This could mean .then
is called on your promise way later in your program, perhaps even asynchronously -
const makePromise = x =>
new Promise(r =>
( console.log("constructing...", x)
, setTimeout(r, 2000, x)
)
)
const a = makePromise("a")
const b = makePromise("b")
const c = makePromise("c")
console.log("construction complete!")
// constructing... "a"
// constructing... "b"
// constructing... "c"
// construction complete!
const main = () =>
Promise.all([a, b, c])
.then(r => console.log("done!", r))
.catch(e => console.error("error!", e))
console.log("please wait 5 seconds...")
setTimeout
( _ =>
( console.log("calling main() now...")
, main()
)
, 5000
)
// calling main() now...
// done
We wrote makePromise
to artificially delay the resolved value by two seconds (2000
milliseconds in the program).
What's critical to notice in this final program is that two seconds begins immediately. By the time we call Promise.all(...).then(...)
five seconds later, all of our Promises have already resolved a value. This is why we see "done"
immediately after main()
is called.
Upvotes: 1
Reputation: 5122
Promise.all
is as its name suggests used to wait that all promises you pass to it get fulfilled.
But since you only want to wait that p1
fulfills, just add .then()
to p1
:
var p1 = new Promise((resolve, reject) => {
console.log('Promise 1');
resolve('Promise 1');
}).then()
The Promise.prototype.then()
method returns a promise. So why not simply put whatever you want to put in p2
in the callback you pass to then()
, like so:
var p1 = new Promise((resolve, reject) => {
console.log('Promise 1');
resolve();
}).then((value) => console.log('Promise 2'))
Upvotes: 2
Reputation: 1075337
When you call new Promise
, the function you pass into it (the promise executor) is run immediately, before you receive the promise back and store it in your variable. The reason for that is that the promise executor function's job is to start an asynchronous process. It can't start it if it isn't called. That's why you see "Promise 2" before "Promise 1", because that's the order you're calling new Promise
.
Also note that Promise.all
doesn't start anything. It just watches the processes that are already in progress and reports on the outcome.
Here's a more realistic use of new Promise
that may help you understand the timing of things: Starting a timer and resolving the promise when the timer fires:
function timer(ms, value) {
return new Promise(resolve => {
console.log(`promise executor called for value "${value}"`);
setTimeout(() => {
console.log(`timer completed for value "${value}", resolving promise`);
resolve(value);
}, ms);
});
}
// Note that I never do anything with the promise `timer` returns
// here, but since it's already started by the time
// it returns, it still does something
console.log("creating anonymous");
timer(800, "anonymous");
console.log("creating p1");
const p1 = timer(1600, "p1");
console.log("creating p2");
const p2 = timer(2400, "p2");
console.log("calling Promise.all([p1, p2])");
Promise.all([p1, p2])
.then(results => {
console.log(`Promise.all promise reseolved with "${JSON.stringify(results)}"`);
})
.catch(error => {
// Normally you'd handle errors here, it's just
// that the promsies from `timer` are never rejected
});
.as-console-wrapper {
max-height: 100% !important;
}
Upvotes: 4
Reputation: 13723
You want to put those strings into the resolve method and then you'll get. what you want. The console.logs inside the actual promises are not asynchronous.
var p2 = new Promise((resolve, reject) => {
resolve('Promise 2');
});
var p1 = new Promise((resolve, reject) => {
resolve('Promise 1');
});
Promise.all([p1]).then(res1 => {
console.log(res1);
return p2
}).then(res2 => console.log(res2))
Upvotes: 2