Javascript 在继续循环之前等待回调
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14408718/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Wait for callback before continue for loop
提问by Muqito
I've a for-loop I'm looping through.
我有一个循环我正在循环。
I want to make a custom modal and wait for a response before continue it.
我想制作一个自定义模式并在继续之前等待响应。
How can I achieve this? I know I've to wait for a callback.
我怎样才能做到这一点?我知道我必须等待回电。
Like this example:
像这个例子:
for(var x in array){
alert(x);
console.log(x);
}
It does exactly what I want to. But I want to have three buttons. But alert is not part of javascript(? It's in the browser.)
它正是我想要的。但我想要三个按钮。但是警报不是 javascript 的一部分(?它在浏览器中。)
So, do you guys have an idea?
那么,你们有什么想法吗?
I was thinking about doing something like this:
我正在考虑做这样的事情:
var run = true;
function foo(){
if (run){
setTimeout(foo, 500);
}
}
function stop(){
run = false;
}
foo();
and then wait for a stop which calls on a button click before continue. But is this really good practice?
然后等待在继续之前调用按钮单击的停止。但这真的是好习惯吗?
Or use a lambda function as a parameter to the customAlert and a "global" variable that holds the current position of the array I'm going through and do this with functions. Like: Check if array is still holding keys greater than X. Then do the function again and each time increase the global X.
或者使用 lambda 函数作为 customAlert 的参数和一个“全局”变量,该变量保存我正在通过的数组的当前位置,并使用函数执行此操作。像:检查数组是否仍然持有大于 X 的键。然后再次执行该功能,每次增加全局 X。
Thank you lostsource for the code: Oh, I got an idea; I'll simply use lostsource's solution inside an anonymous function, so I don't get global variables. Excellent.
谢谢你的代码:哦,我有个主意;我将在匿名函数中简单地使用 lostsource 的解决方案,因此我不会获得全局变量。优秀。
(function(){
})();
回答by lostsource
Assuming this is your array
假设这是你的数组
var list = ['one','two','three'];
You can try using this loop / callback approach
您可以尝试使用这种循环/回调方法
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();
}
Usage:
用法:
// start 'loop'
loopArray(list);
JSFiddle here: http://jsfiddle.net/D9AXp/
JSFiddle在这里:http: //jsfiddle.net/D9AXp/
回答by Beetroot-Beetroot
MaggiQall, I know you have an answer but I have a flexible solution that may be of interest to you or maybe to someone else.
MaggiQall,我知道您有答案,但我有一个灵活的解决方案,您或其他人可能会感兴趣。
The solution depends on jQuery (1.7+) and jQuery UI's dialog, but is implemented as a custom method of the Array prototype, not as a jQuery plugin.
该解决方案依赖于 jQuery (1.7+) 和 jQuery UI's dialog,但作为 Array 原型的自定义方法实现,而不是作为 jQuery 插件。
Here's the Array method :
这是数组方法:
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()relies on :
Array.runDialogSequence()依靠 :
- A dialog template in the document's body, fit to be populated with text/values.
- an array of similar items (typically javascript objects) containing the data required to populate the dialog, in sequence.
- passing, as the first argument, a correctly constructed "openDialog" function.
- 文档正文中的对话框模板,适合填充文本/值。
- 包含按顺序填充对话框所需的数据的类似项目(通常是 javascript 对象)的数组。
- 传递一个正确构造的“openDialog”函数作为第一个参数。
Here's a sample "openDialog" function with explanatory comments :
这是一个带有解释性注释的示例“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()returns a jQuery promise, allowing custom actions to be performed when the dialog sequence completes (done function) or is broken in mid-sequence (fail function).
Array.runDialogSequence()返回一个 jQuery promise,允许在对话序列完成(完成功能)或在序列中间中断(失败功能)时执行自定义操作。
Here are a couple of sample calls :
以下是几个示例调用:
//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 + '"');
});
});
This is as close to a generalized solution as my imagination allows.
这与我的想象所允许的通用解决方案非常接近。

