2015-07-13 2 views
0

У меня возникли проблемы с асинхронным вызовом Javascript. В приведенном ниже классе автомобилей есть функция move, которая принимает два аргумента, первая - это значение, вторая - функция обратного вызова, которая будет вызываться через 1 секунду, и эта функция обратного вызова принимает значение, возвращаемое вперед способ.Javascript async call

var Car = function() { 
    this._count = 0; 
}; 

Car.prototype = { 
    move: function(value, onMoved) { 
    setTimeout(function() { 
     onMoved(this.forward(value)); 
    }.bind(this), 1000); 
    }, 
    forward: function(value) { 
    this._count = this._count + value; 
    return this._count; 
    } 
}; 

Я хочу, чтобы вызвать функцию перемещения, как это:

var values = [1, 2, 3, 4]; 
var car = new Car(); 

values.forEach(function(value) { 
    car.move(value, function(result) { 
    console.log(result); 
    }); 
}); 

Теперь моя проблема заключается в функции обратного вызова onMoved не ждать 1 секунды, чтобы выполнить между каждым значением, которое он выводит , Как я могу сделать это так, чтобы он ждал между каждым значением, которое он выводит? Мне разрешено использовать underscore.js. Благодарю.

+3

«не ждет выполнения 1 секунды» - Да, это так. – Quentin

+1

Вы спрашиваете, как заставить его ждать ** между ** каждым значением, которое оно выводит? На данный момент он ждет одну секунду после запуска вашего (всего) цикла forEach. – Quentin

+0

@Quentin, да, вы правы, я изменил свой вопрос. – user2914136

ответ

1

setTimeout в javascript регистрирует функцию обратного вызова в очереди для выполнения в будущем после того, как текущий стек выполнения является бесплатным. например: -

while(1){ 
setTimeout(function(){ 
    console.log('hello'); 
},1000); 
} 

это не будет печатать привет, так как исполняемый стек никогда не будет бесплатным.

Возвращаясь к примеру, мы вызываем метод перемещения, который будет перенесен в очередь. Через одну секунду он запускает каждую функцию один за другим без какой-либо задержки, так как setTimeout устанавливается на фиксированное время, т. Е. 1000 миллисекунд.

обходной путь: -

var Car = function() { 
    this._count = 0; 
}; 

Car.statCount = 0; 

Car.prototype = { 
move: function(value, onMoved) { 
    this.constructor.statCount++; 
    setTimeout(function() { 
    onMoved(this.forward(value)); 
    }.bind(this), 1000*Car.statCount); 
}, 
forward: function(value) { 
    this._count = this._count + value; 
    return this._count; 
}, 
constructor: Car 
}; 


var values = [1, 2, 3, 4]; 
var car = new Car(); 

values.forEach(function(value) { 
    car.move(value, function(result) { 
    console.log(result); 
    }); 
}); 
+0

Спасибо. Это отлично работает. Можно ли остановить таймер, если результат функции обратного вызова содержит ошибки? – user2914136

+0

, если вам нужно больше контролировать его, используйте метод register для хранения всех и начать перемещение, как только все будут зарегистрированы. Пожалуйста, найдите ссылку, где я изменил пример [ссылка] (http://jsbin.com/xaqavexilo/edit?js,console) – abs

0

Поскольку вы хотите 1 сек. ждать от каждого вызова, вы можете рассмотреть возможность использования метода setInterval на окне, вместо того, чтобы использовать метод SetTimeout:

Вы можете добавить некоторый метод выполнения некоторых действий для каждой итерации, и закончить итерации, когда все значения обрабатываются:

var i=0; 
function go(result) { 
    if (!!values[i]) { 
     car.move(values[i], function(result) {console.log(result);}) 
     i++; 
    } else { 
     window.clearInterval(interval); 
    } 
} 

и вызвать эту функцию с помощью setInterval

var interval = window.setInterval(go, 1000); 

Посмотрите на следующую скрипкой:
https://jsfiddle.net/adw1k98m/1/

(см. Консольный журнал для вывода)