2016-10-04 3 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

, убедитесь, что вы делаете только 5 вызовов myFunction за один раз - затем ждите каждый набор из 5 с помощью Promise.all - но, поскольку это машинопись, может быть совершенно другой способ. –

+1

Ну, это может не быть машинописным, скорее всего, это как .. Но это может быть поток :) – Keith

ответ

4

Вы можете выполнить это, разбив массив на куски и обработав куски, используя Array#map и Promise#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, да, конечно, вы можете сделать это без async/await (странная вещь, чтобы запретить), вы можете выбрать обещания или даже обычные обратные вызовы, но код будет не таким простым. Проверьте 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); 
    } 
}()); 
Смежные вопросы