【问题标题】:wait for a function result in a for loop等待一个函数导致一个 for 循环
【发布时间】:2016-06-16 22:05:42
【问题描述】:

我正在使用 AngularJs 和模块 ngSweetAlert http://oitozero.github.io/ngSweetAlert/#/home,我必须在 for 循环中等待确认按钮功能中的指令执行:

for (var i = 0; i < myArray.length; i++) { 
    SweetAlert.swal({
        title: "Are you sure?",
        text: "Your will not be able to recover this imaginary file!",
        type: "warning",
        showCancelButton: true,
        confirmButtonColor: "#DD6B55",
        confirmButtonText: "Yes, delete it!",
        cancelButtonText: "No, cancel plx!",
        closeOnConfirm: false,
        closeOnCancel: false
    }, function(isConfirm) { 
        if (isConfirm) {
            // Instructions using myArray
        } else {

        }
    });
}

【问题讨论】:

  • @4castle 这与循环中的 JS 闭包无关。它关于使回调的调用阻塞循环的处理。
  • 试一试我的解决方案,但真的很快...您是否要创建 array.length 一次出现的确认框数量?因为我很确定那将是你所拥有的结果。每次调用 sweetalert.swal 函数时,它都会创建一个确认框,因此您可能会获得很多确认框,或者您将获得一个将被覆盖的确认框。您可能希望将甜盒函数调用移出循环
  • @AsadSaeeduddin 你是对的,但他们需要使用闭包来正确执行此操作,否则,i 将是 myArray.length 对于每个回调。
  • 他们偶然需要关闭的事实并不会使这与链接的问题重复。这不是“重复关闭”的用途。

标签: javascript angularjs for-loop sweetalert


【解决方案1】:

编辑:正如 Andrew Luhring 所指出的,原始投票示例不正确

以下是如何使用异步回调样式在前者完成后安排每个警报弹出:

function showAlertNTimes(n) {
    if (n > 0) {
        SweetAlert.swal({...}, function() {
            // Do confirmation stuff 
            showAlertNTimes(n - 1); 
        });
    }

}
showAlertNTimes(myArray.length);

【讨论】:

  • 不是肯定的,但我很确定在不提供退出的情况下调用 while 循环会使页面崩溃。我知道这就是你的“完成”变量应该做的事情。如果您想进行类似的轮询,您可能可以使用 setInterval 来检查每次都完成,然后在完成后使用 clearInterval,但我仍然同意您的观点,这不是解决他的问题的好方法。
  • 是的,你是对的。 while 不适用于单线程 JS。不幸的是,您也不能使用 setInterval 实现阻塞轮询循环,出于同样的原因,您不能直接阻塞警报的结果,它们是接受回调的异步 API。
  • @AndrewLuhring 感谢您的更正,我已经更新了答案。
  • 似乎还有一个swal.queue 用于链接模态的函数。但我不确定 OP 是否使用了足够新的版本。另外,我找不到给排队模式回调的方法。
  • @AsadSaeeduddin 非常感谢!!
【解决方案2】:

使用承诺:

var deferred = $q.defer();
q.resolve(isConfirm); // or whatever ur data is
return deferred.promise;

然后使用“then”来指定应该如何处理返回的promise的结果;

yourFn().then(function(isConfirm){
  //do stuff
});

【讨论】:

  • 这对 OP 的问题没有帮助,即等待循环内回调的执行。
【解决方案3】:

小心,未经测试

不熟悉 swal,但在快速查看它的源代码后,它似乎没有提供承诺,所以我写了一个小包装器(基于 src,在链接的演示页面上):

//since swal doesn't implement promises on it's own, here a wrapper that returns one
function $swal(title, message, type){
    return typeof message === "function"?  $swal(title).then(message):
        typeof title !== "object"? $swal({ title:title, message:message, type:type }):
        config => $q(function(resolve){ window.swal(config, resolve) });
}

这应该和普通的交换函数一样,只是它返回一个承诺。需要 $q 从角度和初始化的 SweetAlert

现在异步变得容易了:

myArray.reduce(function(prev, value, index, arr){
    //wait till the previous promise has been resolved, 
    //then resolve the this one
    return prev.then(function(){
    //return prev.catch(/* error handling for prev */).then(function(){

        //utilize the wrapped function. 
        return $swal({
            title: "Are you sure?",
            text: "Your will not be able to recover this imaginary file!",
            type: "warning",
            showCancelButton: true,
            confirmButtonColor: "#DD6B55",
            confirmButtonText: "Yes, delete it!",
            cancelButtonText: "No, cancel plx!",
            closeOnConfirm: false,
            closeOnCancel: false
        //}).then(function(isConfirm){
        }, function(isConfirm){  //this is just an alias for the previous line
            console.log(index, isConfirm, value);
        });
    });
}, $q.resolve(true));

我传递了一个已解决的 Promise,因此我不必处理它是第一个调用还是依赖调用。

reduce 还包装每个调用的当前索引和值。

还有一件事尚未处理,即您的代码是否抛出错误。

编辑: 正如 4castle 在评论中指出的那样,SweetAlert2 似乎实现了承诺。
那么,您根本不需要 $swal-wrapper,而是使用带有 reduce 的常规 swal 函数。

【讨论】:

    猜你喜欢
    • 2021-02-15
    • 1970-01-01
    • 2014-08-16
    • 2023-01-20
    • 1970-01-01
    • 1970-01-01
    • 2020-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多