我正在閱讀有關異步代碼如何與 javascript 一起作業的 MDN。他們提出了這個例子:
async function myFetch() {
let response = await fetch('coffee.jpg');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
let myBlob = await response.blob();
let objectURL = URL.createObjectURL(myBlob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
}
myFetch()
.catch(e => {
console.log('There has been a problem with your fetch operation: ' e.message);
});
函式 myFetch() 已定義,然后以 Promise 方式呼叫。函式究竟是如何執行的?這是一個異步函式,所以我假設它是給某個執行緒執行的,而不會干擾運行 Javascript 代碼的單個執行緒?同樣在檔案中,他們說 await 會停止該行上的代碼直到完成?所以該函式不能由主應用程式執行緒執行,因為它不再是異步代碼了?所以這些是我的問題,在開始撰寫實際代碼之前,我想確保我理解了這個機制。謝謝!
uj5u.com熱心網友回復:
使用 async/await 與使用 Promise 非常相似,async 函式會為您回傳一個 Promise,該 Promise 可以具有三種狀態之一(待定、已完成、已拒絕)
默認情況下,回傳的 Promise 是 Fulfilled (Resolved) 類似于:
Promise.resolve().then(_ => { //... })
使用 await,Promise 將在您等待的代碼上掛起
new Promise((resolve, reject) => {
// ... some tasks here
resolve(resolvedData);
})
.then(_ => { //... })
當自動或手動拋出錯誤時,Promise 將被拒絕
new Promise((resolve, reject) => {
reject(); // Reject manually
})
.then(_ => { })
.catch(e => { //... })
默認情況下,所有 JavaScript 代碼都在主執行緒中執行,這是 JavaScript 擁有的唯一執行緒
看下面的例子:
async function c() {
const t = await Array.from(Array(100000000).keys())
}
c().then(t => console.log('I am waiting for the Promise to be fulfilled!'))
console.log('Hey, I don\'t need to wait');
您將獲得預期的輸出:
"Hey, I don't need to wait"
"I am waiting for the Promise to be fulfilled!"
但是兩個日志都在等待填充這個100000000陣列,所以主執行緒現在很忙,阻塞了先完成這個任務,JavaScript 本身對這種情況無能為力,
另一個例子:
async function c() {
const t = await fetch('https://jsonplaceholder.typicode.com/photos')
}
c().then(_ => console.log('I am waiting for the Promise to be fulfilled!'))
console.log('Hey, I don\'t need to wait');
在這里你會得到相同的結果,但Hey, I don't need to wait會立即被記錄,并且只會I am waiting for the Promise to be fulfilled!等待,
為什么?在這里我們需要參考一些重要的東西來閱讀更多(事件回圈、呼叫堆疊、微和宏任務)
簡單來說,promise 的行為是一樣的,它正在等待某些東西,代碼中的第一個控制臺日志正在等待 promise 的實作,
the difference is that the task that we are waiting for to have a fulfilled promise now is not thread-blocking, it is not controlled by JavaScript itself
the fetching task is managed by an external API that is observed by the Event loop, in this case, the call stack will not be busy, and the main JavaScript thread can continue working, the code that will resolve the promise is added to a queue and will be pushed to the call stack by the Event loop when the fetching task is done by the external API
uj5u.com熱心網友回復:
函式 myFetch() 已定義,然后以 Promise 方式呼叫。
它像任何其他函式一樣被呼叫。所有async函式都將回傳值包裝在一個 Promise 中,因此有then,catch和finally方法可用。
函式究竟是如何執行的?
()像任何其他功能一樣使用。
這是一個異步函式,所以我假設它是給某個執行緒執行的,而不會干擾運行 Javascript 代碼的單個執行緒?
沒有必要讓它在其他執行緒上運行。正如您所說,JavaScript 執行發生在單個執行緒中。
同樣在檔案中,他們說 await 會停止該行上的代碼直到完成?
是的,在那個異步函式中。
所以該函式不能由主應用程式執行緒執行,因為它不再是異步代碼了?
不必涉及任何執行緒。只有fetch和blob操作是異步執行的。在等待這些操作時,事件回圈和異步函式外的代碼執行將繼續。如果您在呼叫下面有代碼,myFetch那么它將fetch在等待時執行,除非您等待對myFetch自身的呼叫。
async并且await是 Promise 之上的語法糖,因此您的代碼有效地執行以下操作:
fetch('coffee.jpg').then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
response.blob().then(myBlob => {
let objectURL = URL.createObjectURL(myBlob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
});
}).catch(e => {
console.log('There has been a problem with your fetch operation: ' e.message);
});
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/324626.html
標籤:javascript 异步 异步等待
