2016-10-04 69 views
4

對不起,我可能無法清楚地描述這個問題。我會嘗試:如何以組方式調用一個異步函數?

現在我有一個異步功能,它需要數據和做一些事情,例如,

function myFunction(num: number):Promise<void> { 
    return new Promise((resolve) => { 
    console.log(num); 
    return; 
    }); 
} 

我想在組中打印5個數字(順序無關緊要)。重要的是,我希望在上一組完成後打印下5個數字。 例如:

1, 2, 5, 4, 3, 6, 9, 8, 7, 10 ... is valid 
7, 10, 1, 2, 3, 4, 5, 6, 8, 9 ... is not valid 

我怎樣才能做到這一點,如果我要使用這個功能嗎?我必須確保這個功能的前五個調用已經解決,然後調用下面五個函數的調用。我知道這似乎很奇怪,我試圖將我目前的問題提煉成這個數字問題。

謝謝你的任何意見或想法。

+0

這是打字稿?如果是這樣,你應該添加標籤 – evolutionxbox

+2

確保你一次只能對myFunction進行5次調用 - 然後用Promise.all等待每一組5次。但是,因爲這是打字稿,可能會有完全不同的方式 –

+1

可能不是Typescript,最有可能是......但它可能是Flow :) – Keith

回答

4

您可以通過將數組拆分爲塊並使用Array#mapPromise#all處理塊來實現此目的。然後,您可以串起來用Array#reduce塊處理:

runChunkSeries([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5, someAsyncFn); 

// our placeholder asynchronous function 
function someAsyncFn(value) { 
    return new Promise((resolve) => { 
    setTimeout(resolve, Math.random() * 5000); 
    }).then(() => console.log(value)); 
} 

function runChunkSeries(arr, chunkSize, fn) { 
    return runSeries(chunk(arr, chunkSize), (chunk) => Promise.all(chunk.map(fn))); 
} 

// Run fn on each element of arr asynchronously but in series 
function runSeries(arr, fn) { 
    return arr.reduce((promise, value) => { 
    return promise.then(() => fn(value)); 
    }, Promise.resolve()); 
} 

// Creates an array of elements split into groups the length of chunkSize 
function chunk(arr, chunkSize) { 
    const chunks = []; 
    const {length} = arr; 
    const chunkCount = Math.ceil(length/chunkSize); 

    for(let i = 0; i < chunkCount; i++) { 
    chunks.push(arr.slice(i * chunkSize, (i + 1) * chunkSize)); 
    } 

    return chunks; 
} 

這裏的工作codepen

1

我會用發電機,或者因爲使用的是打字稿,你可以使用ES7異步/的await語法和使用lodash你可以做這樣的事情:

(async function(){ 
    const iterations: number = 2; 
    const batchSize: number = 5; 
    let tracker: number = 0; 
    _.times(iterations, async function(){ 
    // We execute the fn 5 times and create an array with all the promises 
    tasks: Promise[] = _.times(batchSize).map((n)=> myFunction(n + 1 + tracker)) 
    await tasks // Then we wait for all those promises to resolve 
    tracker += batchSize; 
    }) 
})() 

您可以替換爲/,而lodash如果你願意,可以循環

檢查 https://blogs.msdn.microsoft.com/typescript/2015/11/03/what-about-asyncawait/

,如果我沒有正確理解或有一些錯誤的代碼,讓我知道,我會更新的答案。

+0

謝謝@Zagen的回覆!我想知道是否有一種方法,而不使用'async'或'await'。在我目前的發展中,這個規則不允許我們使用這些。我可以使用Promise.all(),但我不知道如何編寫此代碼。 – Lubor

+0

@Lubor,當然,你可以做到沒有異步/等待(奇怪的事情來禁止),你可以選擇承諾,甚至定期回調,但代碼不會那麼簡單。檢查SimpleJ答案,它是一個很好的實現,它只使用承諾。 – Zagen

1

它使用async/await其實很簡單:

(async function() { 
    var i = 0; 
    while (true) { 
     for (var promises = []; promises.length < 5;) { 
      promises.push(myFunction(i++)); 
     } 
     await Promise.all(promises); 
    } 
}());