jav*_*ing 4 javascript asynchronous promise async-await
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"))
Run Code Online (Sandbox Code Playgroud)
当我阅读有关承诺时,我知道当我使用 async /await 时,我可以同步打印承诺(在这种情况下是打印:第一个、第二个、第三个、最后一个打印)。现在我也读到同样的事情可以使用 .then 链接来实现,而 async/await 并不是什么“特别”的东西。然而,当我尝试链接我的承诺时,除了“最后打印”的 console.log 之外,什么也没有发生。任何见解都会很棒!谢谢!!
编辑质疑:
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)
})
Run Code Online (Sandbox Code Playgroud)
日志:
starting
(1) first resolved
(2) second resolved
(3) third resolved
third
second
first
Run Code Online (Sandbox Code Playgroud)
1:如果传递给 new Promise 的 executor 函数是立即执行的,在新的 Promise 返回之前,那么为什么这里的 promise 先()同步)在 setTimeouts(异步)执行之后呢?
返回值与解决承诺:
var sync = function () { return new Promise(function(resolve, reject){ setTimeout(()=> { console.log("start") resolve("hello") //--works // return "hello" //--> 什么都不做 }, 3000); }) } sync().then((val)=> console.log("val", val))
在返回新承诺之前,您传递给的 executor 函数会立即new Promise执行。所以当你这样做时:
var p1 = new Promise(function(resolve, reject) {
setTimeout(() => resolve("first"), 5000);
});
Run Code Online (Sandbox Code Playgroud)
...受许被分配到的时间p1,则setTimeout有已经被调用,定于5秒后再回调。无论您是否侦听 promise 的解析,都会发生该回调,无论您是通过await关键字还是then方法侦听解析都会发生该回调。
所以你的代码setTimeouts 立即开始三个,然后开始等待第一个承诺的解决,然后才等待第二个承诺的解决(它已经解决了,所以这几乎是立即的),然后等待第三个(再次相同) .
要让您的代码setTimeout仅在前一个超时完成时按顺序执行这些调用,您必须在前一个 Promise 解决之前不要创建新的 Promise(使用较短的超时以避免大量等待):
var p1 = new Promise(function(resolve, reject) {
setTimeout(() => resolve("first"), 5000);
});
Run Code Online (Sandbox Code Playgroud)
请记住,promise 不会做任何事情,也不会改变promise executor 中代码的性质。所有的承诺确实是提供观察的东西(有非常方便的组合语义)结果的一种手段。
让我们将这三个 promise 的共同部分分解为一个函数:
function delay(ms, ...args) {
return new Promise(resolve => {
setTimeout(resolve, ms, ...args);
});
}
Run Code Online (Sandbox Code Playgroud)
然后代码变得清晰一点:
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");
});Run Code Online (Sandbox Code Playgroud)
现在,让我们把它放在一个async函数中并使用await:
function delay(ms, ...args) {
return new Promise(resolve => {
setTimeout(resolve, ms, ...args);
});
}
Run Code Online (Sandbox Code Playgroud)
通过标准化我们观察异步过程的方式,Promise 使这种语法成为可能。
重新编辑:
1:如果传递给 new Promise 的 executor 函数是立即执行的,在新的 Promise 返回之前,那么为什么这里的 Promise 是先()同步),后
setTimeouts(异步)执行?
这个问题有两个部分:
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")
});
Run Code Online (Sandbox Code Playgroud)
发生的事情是:
new Promise 被调用setTimeout调度回调"first resolved"new Promise 返回并将已解决的承诺分配给 p1"first"到控制台然后你做:
p1.then((val) => {
console.log("(1)", val)
return p2
})
// ...
Run Code Online (Sandbox Code Playgroud)
因为then总是异步调用它的回调,所以异步发生——但很快,因为承诺已经解决。
因此,当您运行该代码时,您会看到所有三个 Promise在第一个setTimeout回调发生之前都已解决——因为这些 Promise 不会等待setTimeout回调发生。
您可能想知道为什么then在您"third"在控制台中看到之前看到您的最终回调运行,因为 Promise 解决方案和console.log("third")Promise 都是异步发生的,但很快(因为它是 asetTimeout(..., 0)并且所有承诺都是预先解决的):答案是那个承诺分辨率是微任务,setTimeout调用是宏任务(或只是“任务”)。任务调度的所有微任务在该任务完成后立即运行(并且它们调度的任何微任务也将被执行),然后从任务队列中取出下一个任务。所以运行你的脚本的任务是这样的:
setTimeout回调安排任务p1的then回调then运行第一个处理程序,调度一个微任务来运行第二个then处理程序then处理程序运行并调度一个微任务来调用第三个then处理程序then处理程序都运行setTimeout回调p3,因此它会运行并"third"出现在控制台中
- 返回值与解决承诺:
您在问题中提出的部分对我来说没有意义,但您对此的评论确实如此:
我读到返回一个值或解决一个承诺是一样的......
什么你可能读过的是返回一个值从then或catch相同返回解决承诺从then或catch。这是因为then与catch创建并返回新的承诺,他们是所谓的时候,如果它们的回调函数返回一个简单的(非承诺)的价值,他们解决他们与价值创造的承诺; 如果回调返回一个承诺,他们会根据该承诺是解决还是拒绝来解决或拒绝他们创建的承诺。
所以例如:
.then(() => {
return 42;
})
Run Code Online (Sandbox Code Playgroud)
和
.then(() => {
return new Promise(resolve => resolve(42));
})
Run Code Online (Sandbox Code Playgroud)
具有相同的最终结果(但第二个效率较低)。
在thenorcatch回调中:
then/catch与价值创造throw ...) 拒绝使用你抛出的值的承诺then/catch的 promise 解决或拒绝您不能使异步代码同步执行。
即便async/await只是语法,让您同步式的控制流程中的承诺。
然而,当我尝试链接我的承诺时,除了“最后打印”的 console.log 之外,什么也没有发生。任何见解都会很棒!
其他函数不生成任何输出。这与他们在承诺中无关。
您启动三个计时器(全部同时),然后记录“最后打印”,然后链接一些承诺,以便在所有三个承诺都解决时(在您开始所有承诺后 5 秒)打印“最后打印”。
如果您希望计时器按顺序运行,那么您必须仅在前一个计时器完成时才启动它们,如果您想查看它们解决的问题,那么您必须编写实际查看它的代码。
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"));Run Code Online (Sandbox Code Playgroud)
Async/await 可以说更简洁:
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");
}());Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5214 次 |
| 最近记录: |