![](/img/trans.png)
[英]Make calls to async function to be executed sequentially in JavaScript
[英]JavaScript nested async function calls executed out of order
一些上下文:我正在嘗試在一個網站上實現一個功能,該功能會在左側打開一個面板,然后插入一個表單來編輯網站上當前顯示的一些信息。 它由點擊事件觸發,並根據用戶在網站上的位置加載不同的表單。 為此,我將數據操作(添加或編輯)和數據目標(應編輯的內容)交給函數。
現在打開面板並填寫信息正在工作,問題是我必須進行幾次中間 API 調用(獲取部分 forms 以插入側面板,加載數據以填充編輯表單)並且我正在獲取異步當我這樣做時,電話混淆了
originalButtonElement 和 sidePanelContainer 發生了一堆事情,但為了簡潔起見,我將把它截斷。
$(document).on('click', '.side-panel-open', async function() {
console.log('opening panel')
await openSidePanel(originalButtonElement, sidePanelContainer);
console.log('opened panel')
async function openSidePanel(originalButtonElement, sidePanelContainer) {
const sidePanelTarget = originalButtonElement.data('side-panel-target');
const sidePanelAction = originalButtonElement.data('side-panel-action');
const apiReturnPromise = $.ajax({
...
}
});
await apiReturnPromise.done(async function (result) {
...
console.log('loading panel')
await loadSidePanelForm(originalButtonElement, sidePanelTarget, sidePanelAction)
console.log('loaded panel');
return Promise.resolve()
.fail(async function () {
throw new Error();
});
async function loadSidePanelForm(originalButtonElement, target, action) {
switch (target) {
case 'editable-element-1':
console.log('getting form');
await loadSidePanelElementOneForm(originalButtonElement, action);
console.log('got form');
return Promise.resolve()
default:
throw new TypeError(`There is no form for ${target}!`);
}
}
async function loadSidePanelElementOneForm(originalButtonElement, action) {
const apiReturnPromise = $.ajax({
...
};
await apiReturnPromise.done(async function (result) {
if (action === 'add') {
...
await loadSidePanelElementOneAddForm(originalButtonElement, sidePanelContainer);
}
else if (action === 'edit') {
...
console.log('loading edit form');
await loadSidePanelElementOneEditForm(originalButtonElement, sidePanelContainer);
console.log('loaded edit form')
return Promise.resolve()
}
}
.fail(async function () {
throw new Error();
});
async function loadSidePanelElementOneEditForm(originalButtonElement, sidePanelContainer) {
const apiReturnPromise = $.ajax({
...
};
await apiReturnPromise.done(async function (result) {
...
return Promise.resolve()
};
.fail(async function () {
throw new Error();
});
}
我了解到,如果 promise 返回某些內容,您只能解析它。 我也明白 ajax 已經返回了 promise 並且如果我理解正確的話 the.done function 然后解決它,因此我為什么這樣寫。 但是,日志消息是亂序的,直到 await 'loadSidePanelElementOneForm(originalButtonElement, action);' 看起來沒問題。
opening panel
loading panel
getting form
opened panel
loading edit form
got form
loaded panel
loaded edit form
我已經在這上面待了幾個小時,但在嘗試了其他幾種選擇后不知所措。 我究竟做錯了什么? 我不確定代碼的哪一部分無法等待其他部分。
我也明白 ajax 已經返回 promise 和 the.done function 然后如果我理解正確的話解決它
不, .done()
不會“解決它”。 它所做的只是安裝一個履行處理程序回調。 當 ajax 請求完成時,promise 自行解析,然后將調用履行/拒絕處理程序。
此外, .done()
不允許像.then()
這樣的操作鏈接,它只是返回不等待處理程序的原始 promise 。 不要使用.done()
/ .fail()
,它們基本上已被棄用多年。
如果您只是使用.then()
而不是,您的代碼可能會起作用,但實際上您也不應該使用它。 您應該只使用await
語法:
$(document).on('click', '.side-panel-open', async function() {
console.log('opening panel')
await openSidePanel(originalButtonElement, sidePanelContainer);
console.log('opened panel')
});
async function openSidePanel(originalButtonElement, sidePanelContainer) {
const sidePanelTarget = originalButtonElement.data('side-panel-target');
const sidePanelAction = originalButtonElement.data('side-panel-action');
const apiReturnPromise = $.ajax({
…
});
const result = await apiReturnPromise;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
…
console.log('loading panel')
await loadSidePanelForm(originalButtonElement, sidePanelTarget, sidePanelAction)
console.log('loaded panel');
}
async function loadSidePanelForm(originalButtonElement, target, action) {
switch (target) {
case 'editable-element-1':
console.log('getting form');
await loadSidePanelElementOneForm(originalButtonElement, action);
console.log('got form');
return;
default:
throw new TypeError(`There is no form for ${target}!`);
}
}
async function loadSidePanelElementOneForm(originalButtonElement, action) {
const result = await $.ajax({
// ^^^^^^^^^^^^^^^^^^^^
…
});
if (action === 'add') {
…
await loadSidePanelElementOneAddForm(originalButtonElement, sidePanelContainer);
} else if (action === 'edit') {
…
console.log('loading edit form');
await loadSidePanelElementOneEditForm(originalButtonElement, sidePanelContainer);
console.log('loaded edit form')
}
}
async function loadSidePanelElementOneEditForm(originalButtonElement, sidePanelContainer) {
const result = await $.ajax({
// ^^^^^^^^^^^^^^^^^^^^
…
});
…
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.