像 alert() 函数一样停止页面执行

IT技术 javascript jquery
2021-03-14 16:40:27

当我写时alert('Hello'),页面执行停止并等待批准继续。

我有一个使用 HTML 显示为假警报div设置 - 这div有一个“确定”按钮。

我希望页面停止执行(就像警报一样),直到用户单击“确定”。

是否可以 ?

6个回答

你不能。只有特殊的内置插件才能做到这一点。有一段时间有一个showModalDialog特殊的内置功能,可以让您为内容指定一个 URI 并因此对其进行自定义,但它从未得到广泛支持,现在甚至被曾经支持它的浏览器弃用。

相反,让您当前的警报功能使用div接受回调关闭警报(或返回关闭时已解决的Promise),以允许您继续处理。

因此,例如,如果您的代码过去使用alert和工作如下:

function foo() {
    var x;

    x = doSomething();
    alert("Alert! Alert!");
    doSomethingAfterTheAlertIsCleared(x);
    doAnotherThingAfterward();
}

...你将其更改为:

function foo() {
    var x;

    x = doSomething();
    fakeAlert("Alert! Alert!", function() {
        doSomethingAfterTheAlertIsCleared(x);
        doAnotherThingAfterward();
    });
}

请注意,现在警报之后的所有代码都在一个函数中,我们将其引用传递到fakeAlert. foo函数在假警报仍在显示时返回,但最终用户解除假警报并调用我们的回调。请注意,我们的回调代码可以访问foo我们正在处理的调用中的局部变量,因为我们的回调是一个闭包(不要担心这是一个相当新和/或神秘的术语,闭包并不复杂)。

当然,如果警报之后唯一的事情是不带任何参数的单个函数调用,我们可以直接传递该函数引用。例如,这个:

function foo() {
    doSomething();
    alert("Alert! Alert!");
    doSomethingAfterTheAlertIsCleared();
}

变成:

function foo() {
    doSomething();
    fakeAlert("Alert! Alert!", doSomethingAfterTheAlertIsCleared);
}

(请注意,没有()after doSomethingAfterTheAlertIsCleared- 我们指的是函数对象,而不是调用函数;fakeAlert将调用它。)

如果您不确定如何fakeAlert调用回调,它将在用户“关闭”警报 div 的事件处理程序中,您只需调用回调的参数,就像对函数的任何其他引用一样. 因此,如果将fakeAlert其作为接收callback,则通过说来调用它callback();

只是为了好玩,我试图“破解”警报/确认对话框,即使我没有成功,我确实注意到,至少在 Chrome 中,可以选中一个框并阻止窗口创建其他模式对话框。因此,即使有人会以某种方式复制相同的行为,这仍然是不够的。这个解决方案就是这样做的方法。
2021-04-16 16:40:27
顺便提一句。你可以停止throw new FatalError("!! Stop JavaScript Execution !!");
2021-05-01 16:40:27
@johnSmith - 这不会做 OP 想要做的事情,它只是终止了该功能。
2021-05-07 16:40:27

是的,这是可能的,我做的这个演示不准确并且没有经过很好的测试。

主要概念:

  1. 在这个例子中,我们有方法 Login.Try() 正在执行 Login.Proceed() 方法。Login.Proceed() 进行 AJAX 查询,我们想等待它的执行,但不想绑定任何处理程序(只需像 window.alert() 那样等待它)
  2. 我们使用 async() 和 await() 方法代替直接函数的执行 Login.Proceed(就像在 C# 中一样)
  3. 当我们需要“暂停”脚本并等待某事时,我们使用 throw 停止方法执行,并解析调用者的函数,以在等待(异步)方法完成执行时运行其第二部分。

什么被排除在范围之外:

  1. 干净的代码
  2. 不同浏览器的测试方案
  3. 保存/恢复局部变量
  4. 不适用于循环。

演示:

<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>

<script>

Login.Try(); // START!! START!! START!!

var Login = {
    Url: "http://xxxx",
    Try: async(this, function (T) {

        console.log('before login');

        //var success = call(this, Login.Proceed); // normal call
        var success = await(this, Login.Proceed);  // that we want!

        console.log('after login');
        console.log('success ' + success);

    }),

    Proceed: function (callback) {
        console.log('before ajax');
        $.ajax({
            url: this.Url,
            context: document.body
        }).done(function () {
            console.log('after ajax');
            callback("role=admin");
        });
    }
}


function async(T, method){
   console.log('before async create');
   return function () { return method.apply(T); };
   console.log('after async create');
};

function await(T, method) {
    var fn = arguments.callee.caller.toString();
    var pos = fn.indexOf('await(');
    var allBeforeAwait = fn.substring(0, pos);

    var pos1 = fn.indexOf('await(');
    pos1 = fn.indexOf(',', pos1) + 1;
    var pos2 = fn.indexOf(')', pos1);
    var cc = fn.substring(pos1, pos2);


    pos = allBeforeAwait.lastIndexOf(';');
    var allBeforeCall = allBeforeAwait.substring(0, pos + 1) + "}";
    var callResult = allBeforeAwait.substring(pos + 1);

    var result = 10;
    var allAfterCall = "("+fn.substring(0, fn.indexOf(")")) + ",V){" + callResult + "V;";
    pos = fn.indexOf(')', pos) + 2;
    allAfterCall = allAfterCall + fn.substring(pos)+")";

    //uncomment to see function's parts after split
    //console.debug(allBeforeCall);
    //console.debug(cc);
    //console.debug(allAfterCall);

    method.apply(T, [function (value) {
        console.log('ajax response ' + value);
        eval(allAfterCall).apply(T, [T, value]);
    } ]);

    throw "";
};

</script>

希望这个演示能激发你的一些想法。

另外,您可以查看http://blogs.msdn.com/b/rbuckton/archive/2011/08/15/promise-js-2-0-promise-framework-for-javascript.aspx

你能上传jsfiddle吗?
2021-04-21 16:40:27
fiddle 在 chrome 上抛出错误,我没有测试其他浏览器...控制台日志:在 ajax (index):108 之前 Uncaught await @(index):108(anonymous function) @(index):52(anonymous function) @( index):74onclick @(index):118(index):65 after ajax (index):104 ajax response role=admin VM498:4 after login VM498:5 success role=admin
2021-04-23 16:40:27
我的整个操作系统都崩溃了,如果我提醒一下,我无事可做,当然我会检查,谢谢
2021-04-23 16:40:27
当然 - jsfiddle.net/vmysla/g3MzL随意使用它。脚本登录浏览器控制台的大部分操作
2021-04-28 16:40:27
嗨@deadManN,谢谢!我修复了那个错误。现在试试。你可以打开控制台看看会发生什么
2021-05-11 16:40:27

您可以使用以下代码长时间暂停执行。

function PauseExecution() {
//做一些事情
sleep(1000);
//做一些事情...

}

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
2021-04-16 16:40:27

不可能像警报那样,但您可以使事情看起来像警报。

例如,您创建了一个调用函数的函数。:) 然后你用一个巨大的 IF 创建一个函数。

window.callfunction = function (f, a, b) /* function name, arguments, boolean*/
{
    var handler = window[f];
    if (typeof handler === 'function') {
        handler(a, b);
    } else {
        alert("No function like that mate, sry.");
    }
}

function deleteAfterConfirm(a, b) /* arguments, boolean */
{
    if (b == true) {
        alert("i can delete, confirmed.");
        alert(a);
        return false;
    }
    magicConfirm(a);
}

function magicConfirm(a) {
    /** 
        modals, popovers, etc, anything you want,
    **/
    $("#confirmModal").modal("show");
    /**
        and put the function's name to the binding element's data
    **/
    $("#returntrue").data("call", arguments.callee.caller.name);
    $("#returntrue").data("arguments", a);
    /** 
        the element like OK button in the alert 
        calls the magicConfirm function's caller function 
        with true, which is the deleteAfterConfirm, and 
        because the bool is true, it will alert i can delete... 
    **/
    $("#returntrue").bind("click", function () {
        callfunction($(this).data("call"), $(this).data("arguments"), true);
    });
}


$(document).ready(function () {
    $("#deleteAfterConfirm").on("click", function () {
        deleteAfterConfirm("variable which is needed later.");
    });
});

所以现在你可以像使用alert() 或confirm() 的函数一样使用deleteAfterConfirm 函数,因为它正在调用其他部分,如果它自己。

不是最好的方法,但这可以以某种方式替换确认和警报以获得更好看的版本。这是假警觉的一种方式:)

玩得开心-R

这不会停止 Javascript 的执行,直到alert被调用。
2021-04-21 16:40:27

您可以使用 Promise API 来实现。这只是关于划分您的代码并在动作侦听器中放置一些行。这是示例代码:

在本例中,有两个按钮。单击第一个按钮启动代码,其余代码将放在promise.then函数上。

html代码:

<body>
  <button id='startButton' onclick='start();'>Start Button</button>
  <button id='targetButton'>Target Button</button>
</body>

脚本代码:

<script>
    function start(){
      console.log('first log'); //put your div displayer code here
      let promise = new Promise(function(resolve, reject) {
          console.log('promise started');
          let targetButton = document.getElementById('targetButton');
          targetButton.addEventListener("click",function(){
            resolve();
          });
      });
      promise.then(function() {
          console.log('second log'); //put the rest of your code
      });
    }
</script>

您将在触发开始按钮后看到first logpromise startedsecond log单击目标按钮后将显示。

Promise API 的资源:

这不会像那样停止 Javascript 的alert执行。
2021-05-10 16:40:27
@Flimm,这是不可能的。如已接受的答案所述。此答案显示了一种在用户操作发生时停止流并恢复流的方法。
2021-05-13 16:40:27