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

Roy*_*mir 45 javascript jquery

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

我有一个 div设置,使用HTML显示为假警报 - 这div有一个'确定'按钮.

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

可能吗 ?

T.J*_*der 42

你不能.只有特殊的内置插件才能做到这一点.有一段时间,有一个showModalDialog特殊的内置功能允许你为内容指定一个URI,从而对其进行自定义,但它从未被广泛支持,现在甚至被曾经支持它的浏览器都弃用了.

相反,制作当前的警报功能,该功能div在警报关闭时使用接受回调(或返回在关闭警报时已解决的承诺),以允许您继续处理.

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

function foo() {
    var x;

    x = doSomething();
    alert("Alert! Alert!");
    doSomethingAfterTheAlertIsCleared(x);
    doAnotherThingAfterward();
}
Run Code Online (Sandbox Code Playgroud)

...你将它改为:

function foo() {
    var x;

    x = doSomething();
    fakeAlert("Alert! Alert!", function() {
        doSomethingAfterTheAlertIsCleared(x);
        doAnotherThingAfterward();
    });
}
Run Code Online (Sandbox Code Playgroud)

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

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

function foo() {
    doSomething();
    alert("Alert! Alert!");
    doSomethingAfterTheAlertIsCleared();
}
Run Code Online (Sandbox Code Playgroud)

变为:

function foo() {
    doSomething();
    fakeAlert("Alert! Alert!", doSomethingAfterTheAlertIsCleared);
}
Run Code Online (Sandbox Code Playgroud)

(注意,()之后没有doSomethingAfterTheAlertIsCleared- 我们指的是函数对象,没有调用函数; fakeAlert会调用它.)

如果您不确定如何fakeAlert调用回调,它将在用户"关闭"警报div的事件处理程序中,您只需调用回调的参数就像对任何其他函数引用一样.因此,如果fakeAlert收到它callback,你可以这么称呼它callback();.

  • 为了好玩,我试图"破解"警报/确认对话框,即使我没有成功,我也注意到,至少在Chrome中,可以选中一个框并阻止窗口创建其他模态对话框.因此,即使有人会以某种方式复制相同的行为,但仍然不够.这个解决方案就是这样做的. (2认同)

Vla*_*sla 10

是的,这是可能的,我做了不准确,并没有很好的测试演示这样做.

主要概念:

  1. 在这个例子中,我们有方法Login.Try()执行Login.Proceed()方法.Login.Proceed()进行AJAX查询,我们想等待它的执行,但不想绑定任何处理程序(只需等待它,因为window.alert()会)
  2. 而不是直接函数的执行Login.Proceed,我们使用async()和await()方法(如在C#中)
  3. 当我们需要"暂停"脚本并等待某事时,我们使用throw停止方法执行,并解析调用者的函数,在等待(async)方法完成执行时运行其第二部分.

什么被排除在范围之外:

  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>
Run Code Online (Sandbox Code Playgroud)

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

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