我是 Javascript 的新手,正在嘗試學習 Promise 和 async/await 概念。我創建了三個承諾,如下所示。
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise1");
resolve("1");
}, 1000)
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise2");
resolve("2");
}, 5000)
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise3");
resolve("3");
}, 4000)
});
我創建了一個 async 函式,它按順序對多個 promise 使用 await,如下所示。
async function example() {
const result1 = await promise1;
const result2 = await promise2;
const result3 = await promise3;
console.log(result1);
console.log(result2);
console.log(result3);
}
example();
瀏覽器控制臺中的輸出是 -
promise1
promise3
promise2
1
2
3
我不明白為什么在我的輸出中 promise3 出現在 promise2 之前,因為在異步函式示例中的 await 陳述句序列中,promise2 出現在 promise3 之前?在我看來,輸出應該如下所示 -
promise1
promise2
promise3
1
2
3
如果我遺漏了什么或有任何錯誤,請糾正我。
uj5u.com熱心網友回復:
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise1");
resolve("1");
}, 1000)
});
當你構造一個 promise 時,它??里面的代碼會立即運行。因此,只要這條線完成,計時器就會關閉并運行。您的代碼預先創建了這些承諾中的 3 個,這意味著它預先啟動了所有 3 個計時器。
稍后當您await承諾時,這不會改變計時器正在做什么。它只是讓您的async函式知道它們何時完成。因此,在后臺,計時器將開始關閉、注銷并解決相應的承諾。即使沒有任何東西在等待承諾,這也可能發生。1000ms 的超時將首先關閉,3 秒后是 4000ms 的超時,然后 1 秒后 5000ms 的超時
如果您希望計時器僅在到達異步函式的該行后啟動,那么您需要在異步函式的該行執行 setTimeouts。例如:
async function example() {
const result1 = await new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise1");
resolve("1");
}, 1000);
});
const result2 = await new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise2");
resolve("2");
}, 5000);
});
const result3 = await new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise3");
resolve("3");
}, 4000);
});
console.log(result1);
console.log(result2);
console.log(result3);
}
uj5u.com熱心網友回復:
簡而言之,這是因為您首先創建了這三個承諾,并且在創建這三個承諾的程序中,您還啟動了三個計時器。這三個計時器都已啟動并并行運行。
然后,你做await promise1。但是,該陳述句與計時器何時呼叫其回呼完全無關。他們將完全靠自己來做到這一點。因此,計時器回呼本身console.log()根據每個計時器設定的預期時間創建輸出(與await您擁有的時間無關)。
因此,它會以這種方式發生,因為您首先創建了所有三個承諾和計時器,然后只有這樣,您才執行await. 這里要理解的一件重要事情是“承諾不執行”。它們本身不是異步操作。一旦你這樣做new Promise(),它就會呼叫承諾執行器函式,并且你在那里的異步操作開始了。從那時起,promise 所做的是監視異步操作,然后在異步操作完成時通知觀察者。
如果在每個計時器啟動時添加日志記錄,您可以看到有關事物順序的更多詳細資訊,這將顯示所有三個計時器最初都啟動并并行運行,并且可以await在代碼后面的陳述句中完全獨立于您的陳述句呼叫它們的計時器回呼:
const promise1 = new Promise((resolve, reject) => {
console.log("starting timer 1");
setTimeout(() => {
console.log("promise1");
resolve("1");
}, 1000)
});
const promise2 = new Promise((resolve, reject) => {
console.log("starting timer 2");
setTimeout(() => {
console.log("promise2");
resolve("2");
}, 5000)
});
const promise3 = new Promise((resolve, reject) => {
console.log("starting timer 3");
setTimeout(() => {
console.log("promise3");
resolve("3");
}, 4000)
});
async function example() {
const result1 = await promise1;
const result2 = await promise2;
const result3 = await promise3;
console.log(result1);
console.log(result2);
console.log(result3);
}
example();
如果您更改了代碼的結構,以便您正在等待的函式實際創建和啟動計時器,那么在第一個計時器觸發之后您將不會啟動第二個計時器,并且您將擁有順序計時器。
所以,如果你這樣做,你的預期輸出會發生:
function runTimer1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise1");
resolve("1");
}, 1000)
});
}
function runTimer2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise2");
resolve("2");
}, 5000)
});
}
function runTimer3() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise3");
resolve("3");
}, 4000)
});
}
async function example() {
const result1 = await runTimer1();
const result2 = await runTimer2();
const result3 = await runTimer3();
console.log(result1);
console.log(result2);
console.log(result3);
}
example();
uj5u.com熱心網友回復:
那是因為您在 async 函式之外創建了 Promises 而沒有等待。Promise 內部的回呼是 syncrounos。您一個接一個地運行 3 個 setTimeout。例子:
const x = new Promise(resolve => console.log(1))
console.log(2)
這會注銷 1,2 - 而不是異步回呼,例如。在 setTimeout 中:
setTimeout(() => console.log(1));
console.log(2)
這會注銷 2,1。
所以,如果你想要正確的行為,你必須在等待它們時創建 Promises,這是常見的做法:
function makePromise(time, number) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise", number);
resolve(number);
}, time);
});
}
async function example() {
const result1 = await makePromise(1000, 1);
const result2 = await makePromise(5000, 2);
const result3 = await makePromise(4000, 3);
console.log(result1);
console.log(result2);
console.log(result3);
}
example();
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/374100.html
標籤:javascript 异步 异步等待 承诺
上一篇:Node.js和MySQL。Promise中的forEach()-最后一項未插入陣列
下一篇:異步抓取網站時編碼錯誤
