var p1 = new Promise(function(resolve, reject) {
setTimeout(() => resolve("first"), 5000);
});
var p2 = new Promise(function(resolve, reject) {
setTimeout(() => resolve("second"), 2000);
});
var p3 = new Promise(function(resolve, reject) {
setTimeout(() => resolve("third"), 1000);
});
console.log("last to print");
p1.then(()=>p2).then(()=>p3).then(()=> console.log("last to be printed"))
As I was reading about promises, I know that I can print promises synchronous (in this case print: first, second, third, last to print) when I use async /await. Now I have also been reading that the same thing can be achieved using .then chaining and async/await is nothing 'special'. When I try to chain my promises, however, nothing happens except for the console.log of "last to be printed". Any insight would be great! Thanks!!
Edit to question:
var p1 = new Promise(function (resolve, reject) {
setTimeout(() => console.log("first"), 5000);
resolve("first resolved")
});
var p2 = new Promise(function (resolve, reject) {
setTimeout(() => console.log("second"), 2000);
resolve("second resolved")
});
var p3 = new Promise(function (resolve, reject) {
setTimeout(() => console.log("third"), 0);
resolve("third resolved")
});
console.log("starting");
p1.then((val) => {
console.log("(1)", val)
return p2
}).then((val) => {
console.log("(2)", val)
return p3
}).then((val) => {
console.log("(3)", val)
})
Loggs:
starting
(1) first resolved
(2) second resolved
(3) third resolved
third
second
first
1: if executor function passed to new Promise is executed immediately, before the new promise is returned, then why are here promises resolved ()synchronously) first and after the setTimeouts (asynchronously) gets executed?
Return value vs. resolve promise:
var sync = function () { return new Promise(function(resolve, reject){ setTimeout(()=> { console.log("start") resolve("hello") //--works // return "hello" //--> doesnt do anything }, 3000); }) } sync().then((val)=> console.log("val", val))
答案 0 :(得分:4)
You cannot make asynchronous code execute synchronously.
Even async
/ await
are just syntax that gives you a synchronous-style control flow inside a promise.
When I try to chain my promises, however, nothing happens except for the console.log of "last to be printed". Any insight would be great!
The other functions don't generate any output. That has nothing to do with them being in promises.
You start three timers (all at the same time), then log 'last to print', then chain some promises so that 'last to be printed' will print when all three promises resolve (5 seconds after you start them all going).
If you want the timers to run sequentially, then you have to initiate them only when the previous one has finished, and if you want to see what they resolve with then you have to write code that actually looks at that.
function p1() {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("first"), 5000);
});
}
function p2() {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("second"), 2000);
});
}
function p3() {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("third"), 1000);
});
}
function log(value) {
console.log("Previous promise resolved with " + value);
}
p1()
.then(log)
.then(p2)
.then(log)
.then(p3)
.then(log)
.then(() => console.log("last to be printed"));
Async/await is, arguably, neater:
function p1() {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("first"), 5000);
});
}
function p2() {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("second"), 2000);
});
}
function p3() {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("third"), 1000);
});
}
function log(value) {
console.log("Previous promise resolved with " + value);
}
(async function() {
log(await p1());
log(await p2());
log(await p3());
console.log("last to be printed");
}());
答案 1 :(得分:2)
您传递给new Promise
的执行程序函数将在返回新的承诺之前立即立即执行。因此,当您这样做时:
var p1 = new Promise(function(resolve, reject) {
setTimeout(() => resolve("first"), 5000);
});
...在将承诺分配给p1
时,setTimeout
已已被调用,并将回调计划了五秒钟。无论您是否侦听承诺的解决方案,都会发生该回调,并且无论您通过await
关键字还是then
方法来侦听解决方案,都会发生该回调。
因此,您的代码立即开始三个setTimeouts
,然后开始等待第一个诺言的解决方案,然后再等待第二个诺言的解决方案(它已经解决了,所以几乎是立即生效的),然后等待第三个(再次相同)。
要让您的代码仅在上一个超时完成时按顺序执行那些setTimeout
调用,您不必在前一个承诺解决之前(使用较短的超时来避免大量等待)才创建新的Promise:>
console.log("starting");
new Promise(function(resolve, reject) {
setTimeout(() => resolve("first"), 1000);
})
.then(result => {
console.log("(1) got " + result);
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("second"), 500);
});
})
.then(result => {
console.log("(2) got " + result);
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("third"), 100);
});
})
.then(result => {
console.log("(3) got " + result);
console.log("last to print");
});
请记住,promise不会做任何事情,并且不会更改promise执行器中代码的性质。 所有的承诺是提供一种观察事物结果的方法(具有非常方便的可组合语义)。
让我们将这三个诺言的共同部分分解为一个函数:
function delay(ms, ...args) {
return new Promise(resolve => {
setTimeout(resolve, ms, ...args);
});
}
然后代码变得更加清晰:
function delay(ms, ...args) {
return new Promise(resolve => {
setTimeout(resolve, ms, ...args);
});
}
console.log("starting");
delay(1000, "first")
.then(result => {
console.log("(1) got " + result);
return delay(500, "second");
})
.then(result => {
console.log("(2) got " + result);
return delay(100, "third");
})
.then(result => {
console.log("(3) got " + result);
console.log("last to print");
});
现在,我们将其放在async
函数中并使用await
:
function delay(ms, ...args) {
return new Promise(resolve => {
setTimeout(resolve, ms, ...args);
});
}
(async() => {
console.log("starting");
console.log("(1) got " + await delay(1000, "first"));
console.log("(2) got " + await delay(500, "second"));
console.log("(3) got " + await delay(100, "third"));
console.log("last to print");
})();
通过使我们观察异步过程的方式标准化,承诺使该语法成为可能。
重新编辑:
1:如果传递给新Promise的执行程序函数在返回新的Promise之前立即执行,那么为什么在这里
setTimeouts
首先(异步)执行(异步)解析Promise? >
这个问题有两个部分:
A)“ ...为什么这里的诺言首先(同步)解决...”
B)“ ......为什么setTimeouts
(异步)执行后,诺言在这里得到解决?”
(A)的答案是:尽管您同步地解决了它们,但then
总是异步调用其回调。这是承诺提供的保证之一。您要在执行程序函数返回之前解析p1
(在该编辑中)。但是,您观察分辨率的方式可确保您依次观察 分辨率,因为直到p2
解决之后,您才开始观察p1
,然后您才观察在解决p3
之前,不要开始观察p2
。
(B)的答案是:它们不是,您要同步解决它们,然后异步观察这些分辨率,并且由于它们已经解决,所以很快就会发生。稍后,计时器回调将运行。让我们看看如何在该编辑中创建p1
:
var p1 = new Promise(function (resolve, reject) {
setTimeout(() => console.log("first"), 5000);
resolve("first resolved")
});
发生了什么事
new Promise
被呼叫setTimeout
安排回调"first resolved"
来兑现诺言new Promise
返回,并将已解决的承诺分配给p1
"first"
输出到控制台然后再做:
p1.then((val) => {
console.log("(1)", val)
return p2
})
// ...
由于then
始终以异步方式调用其回调,因此异步发生-但很快,因为承诺已经解决。
因此,当您运行该代码时,您会看到所有三个承诺在第一个setTimeout
回调发生之前之前解决-因为承诺没有等待setTimeout
回调到发生。
您可能想知道为什么在控制台中看到then
之前,您会看到最终的"third"
回调运行,因为promise决议和console.log("third")
都是异步发生的,但是很快(因为它是setTimeout(..., 0)
,并且承诺都已预先解决):答案是,承诺解决方案是 microtasks ,而setTimeout
调用是宏任务(或仅仅是“任务”)。任务调度的所有微任务在任务完成后立即运行(并且它们调度的所有微任务也将被执行),然后再从任务队列中提取下一个任务。因此,运行脚本的任务会执行以下操作:
setTimeout
回调的任务p1
的{{1}}回调then
处理程序运行,调度一个微任务以运行第二个then
处理程序then
处理程序运行并计划一个微任务,以调用第三个then
处理程序then
处理程序都已运行then
的{{1}}回调,所以它开始运行并且setTimeout
出现在控制台中
- 回报价值与解决承诺:
您在问题中提出的部分对我来说没有意义,但是您对此的评论确实如此:
我读到返回值或解决承诺是一样的...
您可能已经读到,从p3
或"third"
返回值与从then
返回已解决的承诺相同或catch
。这是因为then
和catch
会在被调用时创建并返回新的诺言,并且如果其回调返回简单(非承诺)值,则它们会解析他们的诺言用那个价值创造;如果回调函数返回了一个Promise,则他们会根据该Promise是拒绝还是拒绝来解决或拒绝创建的Promise。
例如:
then
和
catch
具有相同的最终结果(但第二个效率较低)。
在.then(() => {
return 42;
})
或.then(() => {
return new Promise(resolve => resolve(42));
})
回调中:
then
/ catch
then
)会以您抛出的值拒绝该诺言catch
/ throw ...
的承诺根据回调返回的承诺而得到解决或拒绝答案 2 :(得分:0)
如果您需要调用await,但是包含该await的函数不必是异步的,例如因为您需要“数字”而不是“承诺数字”,则可以执行下一步:
var ex: number = new Number(async resolve => {
var f = await funcionExample();
resolve(f);
}).valueOf();