【问题标题】:Javascript executing backwardsJavascript向后执行
【发布时间】:2020-07-07 10:48:19
【问题描述】:

一个应用正在使用带有 InAppBrowser 插件版本 3.2.1 的 Cordova 来加载在 Asp.Net 4.5.2 中构建的网页。我们一直在遇到不稳定的行为,所以我制作了一个页面来发现问题并在这里分享。

此页面包含一个非常简单的按钮,在 onclick event 中执行 JS:

<button onclick="alert('1'); alert('2'); alert('3');"> EXECUTION</button>

完美运行,但是当网站嵌入app时,执行顺序倒退,显示:

  • 警报 3
  • 警报 2
  • 警报 1

使用不显眼的 JS 获得相同的结果:

<button id="testButton">Test</button>
$(document).ready(function () {
    $("#testButton").click(function () {
       alert('1');
       alert('2');
       alert('3');
    });
});

在 ios 中使用 Safari 运行网站效果很好。

有什么想法吗?

更新

正如 @Bergi 在 cmets 中所建议的,添加睡眠 timeout 可以验证管理同步调用的问题。以下代码以正确的顺序触发警报:

$("#testButton").click(function () {
    alert('1');
    setTimeout(function () { alert('2'); }, 2000);
    setTimeout(function(){ alert('3'); }, 4000);
});

但不是在超时更近的时候。以下以错误的顺序显示警报:

$("#testButton").click(function () {
    alert('1');
    setTimeout(function () { alert('2'); }, 1);
    setTimeout(function(){ alert('3'); }, 2);
});

更新 2

正如@Bergi 在 cmets 中提出的,我已经尝试过:

$("#testButton").click(function () {
    var x = []; x.push(1); x.push(2); alert(x);
});

如果结果正确,则会显示一条警报,其中包含:“1,2”。

Issue已被举报。

【问题讨论】:

  • 我猜他们的嵌入没有提供适当的alert 同步版本,一次渲染它们(在彼此之上)。您可以尝试在两者之间添加一些 sleep() 调用来验证这一点。
  • "有什么想法吗?" - 不要使用alert() :-)
  • @MarioLevrero 你是说 actual 代码向后运行(所以这不是警报显示方式的产物)?请同时提供该代码
  • @MarioLevrero 就像您执行var x = []; x.push(1); x.push(2); alert(x) 时会发生什么一样 - 它会引发异常吗?或提醒2,1?还是按预期工作?
  • @Bergi 的第一条评论听起来像是答案。您可以在每个alert() 调用之间通过某种日志记录或断点轻松确认这一点,而不是超时。此浏览器是否支持console.logdebugger 语句?如果没有,您可以在两者之间放置fetchXMLHttpRequest 调用以获取服务器上一些不存在的资源,例如fetch("log-one")fetch("log-two")。获取将失败并出现 404 错误,但您可以检查服务器日志以查看它们到达的顺序。我敢打赌,在您点击任何警报之前,它们都会连续到达。

标签: javascript cordova cordova-plugins inappbrowser


【解决方案1】:

正如@Bergi 在评论中建议的那样,您调用的alert() 版本在某些平台上可能是异步的,而在其他平台上可能是同步的。这可以解释您所看到的行为。

根本不用window.alert(),当您需要警报框时,您可能应该使用cordova-plugin-dialogs 中的navigator.notification.alert()

注意这个函数的签名:

navigator.notification.alert( message, alertCallback, [title], [buttonName] )

alertCallback 函数在警报框消失后被调用。即使有些实现是同步的(因为它们使用原生浏览器alert() 函数)而有些是异步的,navigator.notification.alert() 为这两种情况提供了兼容的接口。

嗯,大部分兼容。在navigator.notification.alert() 调用本机alert() 的平台上,在用户关闭警报框之前,该函数不会返回。在使用其他实现的平台上,该函数可能会立即返回。但在这两种情况下,alertCallback 都会在警报框被解除时被调用。

cordova-plugin-dialogs 还提供了 navigator.notification.confirm()navigator.notification.prompt() 的类似实现,每个都有完成回调。

cordova-plugin-inappbrowser 在tests.js 中有一段有趣的代码:

window.alert = window.alert || navigator.notification.alert;
if (isWindows && navigator && navigator.notification && navigator.notification.alert) {
    // window.alert is defined but not functional on UWP
    window.alert = navigator.notification.alert;
}

请注意此函数如何在没有 window.alert 的平台以及 UWP 上将 window.alert 设置为与 navigator.notification.alert 相同。虽然与您的情况没有直接关系,但这说明了在不同平台上可能会有不同的实现。但是使用navigator.notification.alert() 应该可以让您为所有人编写兼容的代码。只是不要假设这个函数是立即返回还是等待警报被解除 - 请改用alertCallback

【讨论】:

  • 谢谢,@Michael。我理解它,但我看到的问题是 webPage 层必须考虑嵌入到 Cordova 插件中,我认为这与适当的层设计不符。
  • 我们在从 Asp 页面使用 __doPostBack() 调试类似错误时意识到了这个 alert 管理。即使 Cordova-PlugIn 有 alert() 的实现,__doPostBack 的问题仍然存在
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 2012-06-28
  • 1970-01-01
  • 2020-04-29
  • 1970-01-01
  • 2013-09-25
相关资源
最近更新 更多