簡體   English   中英

JavaScript 嵌套異步 function 調用亂序執行

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM