Подождите, пока обратный вызов не продолжит цикл
У меня есть цикл for, который я просматриваю.
Я хочу создать собственный модальный режим и дождаться ответа, прежде чем продолжить его.
Как я могу это достичь? Я знаю, что я должен ждать обратного вызова.
Как этот пример:
for(var x in array){
alert(x);
console.log(x);
}
Он делает именно то, что я хочу. Но я хочу иметь три кнопки.
Но предупреждение не является частью javascript (? Оно в браузере.)
Итак, у вас, ребята, есть идея?
Я думал о том, чтобы сделать что-то вроде этого:
var run = true;
function foo(){
if (run){
setTimeout(foo, 500);
}
}
function stop(){
run = false;
}
foo();
а затем дождитесь остановки, которая вызывает нажатие кнопки перед продолжением. Но действительно ли это хорошая практика?
Или используйте лямбда-функцию в качестве параметра для customAlert и "глобальной" переменной, которая содержит текущую позицию массива, который я просматриваю, и делаю это с помощью функций. Например: проверьте, сохраняет ли массив все ключи, отличные от X.
Затем снова выполните функцию и каждый раз увеличивайте глобальный X.
Спасибо, потерянный источник для кода:
О, у меня появилась идея; Я просто использую решение lostsource внутри анонимной функции, поэтому я не получу глобальных переменных. Отлично.
(function(){
})();
Ответы
Ответ 1
Предполагая, что это ваш массив
var list = ['one','two','three'];
Вы можете попробовать использовать этот подход цикла/обратного вызова
var x = 0;
var loopArray = function(arr) {
customAlert(arr[x],function(){
// set x to next item
x++;
// any more items in array? continue loop
if(x < arr.length) {
loopArray(arr);
}
});
}
function customAlert(msg,callback) {
// code to show your custom alert
// in this case its just a console log
console.log(msg);
// do callback when ready
callback();
}
Использование:
// start 'loop'
loopArray(list);
JSFiddle здесь: http://jsfiddle.net/D9AXp/
Ответ 2
MaggiQall, я знаю, что у вас есть ответ, но у меня есть гибкое решение, которое может вас заинтересовать или, возможно, кому-то еще.
Решение зависит от jQuery (1.7+) и jQuery UI dialog
, но реализовано как пользовательский метод прототипа Array, а не как плагин jQuery.
Здесь метод массива:
Array.prototype.runDialogSequence = function(dialogCallback, startIndex, endIndex){
startIndex = Math.max(0, startIndex || 0);
endIndex = Math.min(this.length - 1, endIndex || this.length - 1);
var sequenceIndex = 0,
arr = this,
dfrd = $.Deferred().resolve(startIndex);
function makeCloseFn(seqData){
return function(event, ui){
if(seqData.continue_) { seqData.dfrd.resolve(seqData.arrayIndex+1, seqData); } //continue dialog sequence
else { seqData.dfrd.reject(seqData.arrayIndex, seqData); } //break dialog sequence
}
}
$.each(this, function(i){
if(i < startIndex || i > endIndex) { return true; }//continue
dfrd = dfrd.then(function(arrayIndex){
var seqData = {
dfrd: $.Deferred(),
arrayIndex: arrayIndex,
sequenceIndex: ++sequenceIndex,
length: 1 + endIndex - startIndex,
item: arr[arrayIndex],
continue_: false
};
dialogCallback(seqData).on("dialogclose", makeCloseFn(seqData));
return seqData.dfrd.promise();
});
});
return dfrd.promise();
}
Array.runDialogSequence()
полагается на:
- Шаблон диалога в теле документа, который будет заполнен текстом/значениями.
- массив похожих элементов (обычно объектов javascript), содержащих данные, необходимые для заполнения диалога, в последовательности.
- передает в качестве первого аргумента правильно построенную функцию "openDialog".
Здесь образец "openDialog" с пояснительными комментариями:
function openDialog(seqData){
/*
seqData is an object with the following properties:
dfrd: A Deferred object associated with the current dialog. Normally resolved by Array.runDialogSequence() to run through the sequence or rejected to break it, but can be resolved/rejected here to force the dialog sequence to continue/break. If resolved, then pass (seqData.arrayIndex+1, seqData), or custom values. If rejected, typically pass (seqData.arrayIndex, seqData).
arrayIndex: The current array index.
sequenceIndex: The current index within the sequence. Normally the same as arrayIndex but Differs when a non-zero startIndex is specified.
length: The full length of the dialog sequence.
item: The current item from the array.
continue_: (false) Set to true to allow the sequence to continue.
*/
var item = seqData.item;
var $d = $("#d");
$d.dialog({
title: 'Dialog (' + seqData.sequenceIndex + ' of ' + seqData.length + ')',
modal: true,
buttons: {
"Continue": function(){
seqData.continue_ = true;//set to true before closing to go to next dialog.
$(this).dialog("close");
},
"Cancel": function(){
$(this).dialog('close');//closing with seqData.continue_ set to its default value false will break the dialog sequence.
}
}
}).find("#message").text(item);//Typically you will do a lot more here to populate the dialog with item data.
return $d;//openDialog() must return a dialog container, jQuery-wrapped.
}
Array.runDialogSequence()
возвращает jQuery promise
, позволяя выполнять пользовательские действия, когда последовательность диалога завершается (выполняемая функция) или прерывается в середине последовательности (функция отказа).
Вот несколько примеров вызовов:
//Simplest possible
$("#myButton1").click(function(){
myArray.runDialogSequence(openDialog);
});
//Call with custom startIndex and endIndex, and chanined `.then()` to provide custom actions on break/completion.
$("#myButton2").click(function(){
myArray.runDialogSequence(openDialog, 1, 3).then(function(i, seqData){
alert('All dialogs complete - last item = "' + seqData.item + '"');
}, function(i, seqData){
alert('Dialog sequence was broken at item ' + i + ' "' + seqData.item + '"');
});
});
DEMO
Это как можно ближе к обобщенному решению, как позволяет мое воображение.