簡體   English   中英

在JavaScript中,如何獲取數組所有元素的回調function的結果,並對其執行一些邏輯?

[英]In JavaScript, how to get back the results of a callback function for all the elements of an array, and execute some logic on them?

我有一個調用 API 的 function,API 接受回調:

const callApi = async (param1, param2) => {
    api.doSomething(param1, param2, (result) => {
        // I want to return the result as the result of callApi
    }
}

我有一個對象列表/數組,我想在這些對象上調用 Api function,逐一處理結果,然后對它們進行排序並選擇符合我的標准的對象。

我不想把所有的邏輯都放在回調中。 我知道我可以,但它會導致代碼難看,一年后將很難閱讀。

就像是:

let results = myArrayOfObjects.map(function(myObject){
    callApi(myObject.field1, myObject.field2)
        .then(
            // here I'd like to get the result of api.doSomething
            // do more stuff here with that result
        )

    // return an object here, or a promise

})

// do something with the results after all objects in myArrayOfObjects have been processed
// for example, sort()

如果結果是承諾,我正在考慮使用 Promise.all 等待它們全部完成。 否則,使用結果會更容易。

謝謝。

您可以首先承諾您的 API 以便它返回一個 Promise 解析為您的回調提供的結果。 可能值得檢查您的 API 實現並查看它是否已經返回 Promise(如果是這樣,那么您可以返回 Promise 並放棄回調)

const callApi = (param1, param2) => {
  return new Promise(resolve => { 
    api.doSomething(param1, param2, (result) => {
        resolve(result);
    });
  });
}

一旦你有callApi返回 Promise,你可以 map 在你的數組上調用callApi()來觸發你的 API 請求,以及返回 Promise。此時你可以通過附加一個 .then .then()來擴展你的 promise 鏈它並返回 Promise 的轉換版本:

const mapped = myArrayOfObjects.map(myObject => {
    return callApi(myObject.field1, myObject.field2)
        .then(result => // result of api.doSomething
            // do more stuff here with that result
            return result2; // return the transformed result (ie: `result2`)
        );
});

上面的代碼可以使用 async/await isstead 重新編寫得更好一點:

const mapped = myArrayOfObjects.map(async myObject => {
    const result = await callApi(myObject.field1, myObject.field2);
    // do more stuff here with that result
    return result2; // result2 represents the "mapped"/transformed version of `result`
});

一旦你有一個映射到你想要的值的承諾數組,你可以使用Promise.all()來等待所有承諾解決並檢索你的結果:

Promise.all(mapped).then(results => {
    // results is an array based on the mapped values
});

簡單示例(使用 setTimeout 模擬異步 API 請求):

 const callApi = (n) => { return new Promise(resolve => { setTimeout(() => { const result = Math.random() + n; resolve(result); }, 1000); }); } const mapped = [1, 2, 3].map(async n => { const result = await callApi(n); const result2 = `Random number is: ${result}`; return result2; // result2 represents the "mapped"/transformed version of `result` }); Promise.all(mapped).then(results => { console.log(results); });

不要使用.then(),而是創建一個 function 來執行您希望它執行的所有操作,然后將該 function 作為參數發送到 callApi 中。

const doStuff = (results) => {
    // Do stuff here
}

callApi(myObject.field1, myObject.field2, doStuff)

然后在調用Api function:

const callApi = async (param1, param2, stuffDoerFunc) => {
    api.doSomething(param1, param2, stuffDoerFunc);
}

現在我考慮了一下,您甚至可以進一步簡化它:

const doStuff = (results) => {
    // Do stuff here
}

api.doSomething(myObject.field1, myObject.field2, doStuff);
// Wrap your object/array processor in a standalone function
function processObjects() {
    let results = myArrayOfObjects.map(function(myObject){
        callApi(myObject.field1, myObject.field2)
            .then(
                // here I'd like to get the result of api.doSomething
                // do more stuff here with that result
            )    
    
        // return an object here, or a promise
    
    })
}

// Wrap your post-processing in a second function
function processResults() {
    // do something with the results after all objects in myArrayOfObjects have been processed
    // for example, sort()
}

// Create a master function to call, which calls both functions in order, 
// and does not let the second one start until the first one completes
async function processObjectsThenResults() {
    await processObjects();
    await processResults();
}

所有這些魔法在順序函數語言中都是不必要的,但在 JS 的同步沼澤中,你需要強制它等到你的第一組命令完成后再開始后處理,否則它會嘗試一次完成所有操作重疊和混亂將接踵而至!

要修改此方法以傳遞結果,您可以將它們從一個 function 推送到另一個。 一個 hacky 的方法是將第一個 function 的結果傳遞給第二個,如下所示:

async function processObjectsThenResults() {
    someArrayVariable = await processObjects();
    await processResults(someArrayVariable);
}

您需要調整第二個 function 才能以第一個 function 輸出的格式接收和解釋參數。

暫無
暫無

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

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