2016-06-27 2 views
1

Извините, если этот вопрос был задан раньше - я не нашел ответ для своего дела.Функции Queuing js

У меня есть одна функция, которая будет вызываться снова и снова асинхронно.
Мне нужно избегать параллельного выполнения этой функции.

Вот пример:

const q = // some kind of queue; 

let v = 0; 
const fun = (arg) => { 
    console.log('v', v) 
    setTimeout(() => { 
     v = v + arg; 
     // return true; 
     q.next() 
    }, 1000) 
} 


q.add(fun(2)) 
q.add(fun(3)) 
q.add(fun(4)) 
q.add(fun(5)) 

Это журналы я хочу видеть в конце:

v 0 
v 2 
v 5 
v 9 
v 14 
+0

Посмотрите на библиотеку асинхронным. Он делает это для вас https://github.com/caolan/async. В частности, функция «series (...)» – bhspencer

+0

'fun()' ничего не возвращает, чего вы ожидаете поставить в очередь? – Barmar

+0

@Barmar Я намерен поставить там довольно сложные функции с асинхронными вызовами. Мне нужно иметь способ сказать, что «эта функция закончена, проверьте, есть ли следующая» в каждой из функций в очереди. – stkvtflw

ответ

1

Вы можете просто использовать массив.

Обратите внимание, что вывод моего кода немного отличается от вашего - я не получаю «v 14». Я не уверен, почему вы ожидаете этого вывода ... вы ставите в очередь четыре вызова функций, но ожидаете пять строк вывода?

const q = []; 

let v = 0; 
function fun (arg) { 
    console.log('v', v); 
    setTimeout(() => { 
    v = v + arg; 
    var next = q.shift(); 
    if (next) { next(); } 
    }); 
} 

q.push(() => { fun(2); }); 
q.push(() => { fun(3); }); 
q.push(() => { fun(4); }); 
q.push(() => { fun(5); }); 

q.shift()(); // run the first one 

// OUTPUT: 
// v 0 
// v 2 
// v 5 
// v 9 

EDIT

Вот, возможно, лучший вариант, который имеет дополнительное преимущество, что он будет работать должным образом, независимо от того, когда все помещён. В приведенном выше коде вам нужно вручную запускать что-то, и как только очередь будет исчерпана, ничто позднее не будет добавлено. В приведенном ниже FunctionQueue классе, выполнение происходит автоматически всякий раз, когда есть по крайней мере одна функция для запуска:

class FunctionQueue { 
    constructor() { 
    this.queue = []; 
    this.running = false; 
    } 

    go() { 
    if (this.queue.length) { 
     this.running = true; 
     this.queue.shift()(() => { this.go(); }); 
    } else { 
     this.running = false; 
    } 
    } 

    add(func) { 
    this.queue.push(func); 

    if(!this.running) { 
     this.go(); 
    } 
    } 
} 

let v = 0; 
function fun (arg, cb) { 
    console.log('v', v); 
    v += arg; 
    setTimeout(cb, 100); 
} 

const q = new FunctionQueue(); 
// Execution will automatically start once something is enqueued. 
q.add((cb) => { fun(2, cb); }); 
q.add((cb) => { fun(3, cb); }); 
q.add((cb) => { fun(4, cb); }); 
q.add((cb) => { fun(5, cb); }); 

// At this point, nothing's running anymore. 

// Enqueueing something much later will resume execution again. 
setTimeout(() => { 
    q.add((cb) => { fun(6, cb); }); 
}, 1000); 

// OUTPUT: 
// v 0 
// v 2 
// v 5 
// v 9 
// v 15 
+0

Как добавить новый за 10 минут после первого запуска? – stkvtflw

+0

@stkvtflw См. Мое редактирование, которое должно хорошо обработать этот случай. – smarx

+0

спасибо! Простой и эффективный) – stkvtflw

0

Вы можете использовать Promise. Любое разрешение первого, вызовите вторую и так далее ..

let v = 0; 
const fun = (arg) => { 
    return new Promise((resolve, reject) => { 
    setTimeout(() => { 
     console.log('v', v) 
     v = v + arg; 
     resolve(true); 
    }, 1000) 
    }); 
} 

var promise = func(0); 
for (var i =1; i< 10; i++){ 
    (function(n){ 
    promise = promise.then(()=>{ 
     return func(n); 
    }); 
    })(i); 
} 
+0

, как добавить новый за 10 минут после первого выполнения? – stkvtflw

+0

Я обновил свой ответ –

0

Это будет начато с fun() и продолжать работать, пока там увеличивают определение осталось в очереди:

const queue = []; 
 

 
const fun = (start) => { 
 
    start = start || 0 
 
    console.log('v', start) 
 
    setTimeout(() => { 
 
     if(queue.length > 0) { 
 
      const increment = queue.shift(); 
 
      fun(start + increment); 
 
     } 
 
    }, 1000) 
 
} 
 

 
queue.push(2) 
 
queue.push(3) 
 
fun() 
 
queue.push(4) 
 
queue.push(5)

Обратите внимание, что в зависимости от вашего браузера, const ключевого слова может не поддерживаться и его необходимо перевести на ES5 или заменить на ключевое слово var.