簡體   English   中英

僅在遞歸完成后,如何才能做出Promise解決方案?

[英]How can I make a Promise resolve only after recursion is completed?

我在使這種邏輯正常工作時遇到問題,我什至不知道是否有可能或我是否在此處正確使用了Promise。

我有第一個函數,它接收一個ID列表,這些ID用於發出請求以提取特定的異步數據。 我一次只能拉入1000,因此,如果列表包含的數目超過1000,則必須遞歸遍歷。

我正在尋找的是-對於需要遞歸的每個選項,請調用遞歸函數, 等待結果,然后將其推入列表。 獲得所有數據后,請對數據進行響應。

async function getData () {
    .... 
    // Inside condition that determines it needs to recurse
    let _data = await _getOptions(id, data, 0);
    dataList.push(_data);
    ...
    // Eventually, return the data
    res.json(dataList);
}

該函數遍歷列表,並且應該在所有數據輸入后解決。

let rData = [];
function _getOptions(id, data, offset) {
    return new Promise((resolve, reject) => {
        if (data.length < 1000) {
            return resolve(rData);
        }
        let fields = { fields: `id, key_value, label, condition_value`, offset: offset, limit: 1000 };
        options.getOptionsWithFilter(id, fields, (err, data) => {
            rData.push(data);
            _getOptions(id, data, offset + 1000);
        });
    });
}

似乎由於控制台中拋出錯誤而無法正常工作,這向我暗示它正在返回undefined 我想問題是我在這里使用了錯誤的Promise。 但我一直在努力提出另一種解決方案。 我需要繼續在_data變量中返回所有數據。

您的promise構造函數回調應始終會導致調用resolve (或reject ),但是當您繼續進行遞歸調用時,就永遠不會在該特定的 promise上調用resolve 所以這樣稱呼它:

resolve(_getOptions(id, data, offset + 1000));

我還認為您組合結果數據塊的方式是錯誤的:您會將數組作為嵌套數組推入最終數組。 我希望您需要將這些塊連接成一維數組。

data變量的使用存在問題:您將它用於傳遞給_getOptions函數的內容(不確定最初的含義),還用於getOptionsWithFilter 提供的內容 我認為后面的數據實際上是您要處理的唯一data 因此,您無需將其傳遞給_getOptions

最好避免使用全局rData變量。 由於僅將其設置為空數組一次,因此冒着沒有為要發出的下一個請求清除它的風險。

取而代之的是讓最終的承諾產生最終的數據塊,然后在其之前添加之前的數據塊:

function _getOptions(id, offset = 0) { // No data argument!
    return new Promise((resolve, reject) => {
        let fields = { fields: `id, key_value, label, condition_value`, 
                       offset: offset, limit: 1000 };
        options.getOptionsWithFilter(id, fields, (err, data) => {
            if (data.length < 1000) { // Perform the check when you have the data
                return resolve(data); // just this chunk
            }
            resolve(_getOptions(id, offset + 1000) // Don't pass data
                       // prepend this data to the data that the recursive 
                       // promise will provide
                       .then(rData => data.concat(rData))
            );
        });
    });
}

您這樣稱呼它:

_data = await _getOptions(id);

選擇:一個承諾

您還可以選擇在一個Promise構造函數回調中執行異步循環(“遞歸調用”):

function _getOptions(id) { // No data argument!
    return new Promise((resolve, reject) => {
        let rData = [];
        (function loop(offset) {
            let fields = { fields: `id, key_value, label, condition_value`, 
                           offset: offset, limit: 1000 };
            options.getOptionsWithFilter(id, fields, (err, data) => {
                rData = rData.concat(data);
                if (data.length < 1000) { // Perform the check when you have the data
                    return resolve(rData); // All retrieved data
                }
                loop(offset + 1000); // Collect more
            });
        })(0); // Call immediately
    });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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