同步 ajax 调用 - 在调用前显示 div
synchronous ajax call - show div before call
我需要在同步 ajax 调用之前显示覆盖我整个屏幕的 div。
但似乎我尝试做的任何事情都不会导致 DOM 被修改为在 ajax 调用之前显示此 div。屏幕变为 "frozen",仅在执行 ajax 调用后才显示 div。
我已经尝试了 "thousands" 的方法,但似乎只有在修改 DOM 之后才 ajax 运行(显示 div) .
HTML
[...]
<body>
<div id="loadingDiv" style="display: none; width: 100%; height: 100%; background-color: #004000; position: absolute; z-index:10000;"></div>
[...]
javascript
[...]
$("#loadingDiv").css("display", "block");
var ajaxOp;
$.ajax({
type: someType,
url: someUrl,
data: someData,
dataType: someDataType,
async: false,
success: function (someArg) {
ajaxOp = someArg;
},
error: function (someArg0, someArg1, someArg2) {
// do something
}
});
return ajaxOp;
[...]
注意 I: 我正在使用 JQuery.
注意二:"ajaxOp"不能"undefined".
更新: 希望它有助于理解,应@Felipe Dutra Ferreira 的要求,我在下面的更新中对这个问题做了更多解释......
真实案例:我有一个包含多个遗留代码的应用程序,这些代码使用一个函数 libray js,该函数反过来进行 ajax 调用(我们称之为 "certainfunction")。我们正在尝试更新此应用程序,以便它在 ajax 调用期间显示 "loading screen"(而不仅仅是在这些调用期间显示 "lock" 和 UI)。因此,处理此问题的最简单方法是在 "certainfunction" 调用之后和 运行 调用 ajax 之前显示 "loading screen"。另请注意,"certainfunction" returns 来自 ajax 调用的输出和此输出将是 "undefined" 一旦此调用未同步执行,即代码只能在之后继续此 ajax 调用有一个输出。
我已经为你写了以下内容。
请查看我的 GITHUB
中的以下示例
因为我有一个完整的示例,我已尽力帮助您。
在这里您将看到 Jquery 回调方法和承诺框架的使用,这似乎是您遇到的问题。请回复我,让我知道这是否是最终解决方案,因为我决心帮助您。
点击JSBin查看我的示例=>
https://jsbin.com/xeloful/edit?html,output
<body onload="myFunction()" style="margin:0;"></body>
我想提请您注意...
如果您仍然需要帮助,请与我们联系...或者如果这没有帮助...
或者您可以 运行 Whosebug 上的代码片段。下面我使用 $(myFunction)
而不是 onload="myFunction()"
,这对于 jQuery 用户来说更为传统。点击下面的"Run Snippet"查看结果。
function showPage() {
document.getElementById("loader").style.display = "none";
document.getElementById("myDiv").style.display = "block";
};
function myFunction() {
//Showing a Div prior to call as promised...
$("#redSquare").fadeIn(3000).fadeOut(3000, function () {
//Making the following API Call that will receive a random email from a random user...
$.ajax({
url: 'https://randomuser.me/api/',
dataType: 'json',
success: showPage
}).done(function (res, req) {
//Spitting out information about the HTTP call made...
console.log(res);
console.log(req);
//Storing the email in the following variable...
var RandomEmail = res.results[0].email;
//Displaying the email in the console...
console.log(RandomEmail);
//Injecting the following email to the DOM
document.getElementById("randomEmail").innerHTML = RandomEmail;
});
});
}
//When the body loads, render this function as seen in the body HTML tag with the onload... This is the jQuery way to do it...
$(myFunction);
#redSquare {
display: none;
width: 100vw;
height: 100vh;
background-color: crimson;
}
/* Center the loader */
#loader {
position: absolute;
left: 50%;
top: 50%;
z-index: 1;
width: 150px;
height: 150px;
margin: -75px 0 0 -75px;
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Add animation to "page content" */
.animate-bottom {
position: relative;
-webkit-animation-name: animatebottom;
-webkit-animation-duration: 1s;
animation-name: animatebottom;
animation-duration: 1s
}
@-webkit-keyframes animatebottom {
from {
bottom: -100px;
opacity: 0
}
to {
bottom: 0px;
opacity: 1
}
}
@keyframes animatebottom {
from {
bottom: -100px;
opacity: 0
}
to {
bottom: 0;
opacity: 1
}
}
#myDiv {
display: none;
text-align: center;
}
#randomEmail {
color: white;
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="redSquare">
<!--Making this Appear for 3 Seconds prior to Ajax...-->
</div>
<div id="loader"></div>
<div style="display:none;" id="myDiv" class="animate-bottom">
<h2>Tada!</h2>
<p>Some text in my newly loaded page..</p>
<h1>
RandomEmail: <span id="randomEmail"></span>
</h1>
</div>
一个解决方法是使用下面的函数,当我们进行同步调用("ajax")时,允许在系统上显示一个"loading screen"。它可以很容易地适应遗留代码。
意识到 "ajax" 阻止了对 "DOM" 的修改,即使它是在本次调用之前执行的。只有在涉及之前的一些同步 ajax 调用的进程的第一次使用时,这种方法才有效。基本上,它会在执行所需的 function/method("appFunc")之前创建一个时间 window(50 毫秒)来更新 DOM。只有在需要在执行后立即使用同步 ajax 调用输出的情况下,使用此函数才有意义。
使用示例:<button type="button" onclick="opSyncLoading(login, [this.form])">
- 在这个例子中我们利用用户操作的"eventuality"创建一个时间window到线程并显示"loading screen"。请注意,"login" 函数不会 return 任何类型的输出。请注意,在 "login" 函数之后发生的所有事情都将以 "SYNC" 方式完成。
- 这个限制是因为 JS/DOM 只有一个 "thread" 来处理所有事情,也就是说,没有办法用 "sleep" 等待,例如,因为不存在任何类型的有效并行性。一种解决方案可能是使用 "web worker",但这超出了所提出问题的范围。
- 必须避免使用同步 "ajax" 调用,因为它会对 JS 的操作和 HTML 响应能力造成副作用,而且会被视为不良做法。它的使用应仅限于遗留代码或绝对必要的情况。
提示: 请注意,如果 "loading screen" 上有动画 gif,它将 "locked" 直到 "ajax" 调用完成,但是在某些现代浏览器中不会发生此问题。在极端情况下,如果图像加载到 iframe () 中,图像可能会保持 "animated"。
function opSyncLoading(appFunc, appFuncArgs) {
if (typeof appFuncArgs === "undefined" || appFuncArgs === "") {
appFuncArgs = [];
}
$("#loadingDiv").fadeIn(500, setTimeout(function () {
// NOTE: Passing unknown arguments in quantity and nature to a callback function. By Questor
// [Ref.: ]
appFunc.apply(this, appFuncArgs);
}, 50));
}
谢谢! =D
我需要在同步 ajax 调用之前显示覆盖我整个屏幕的 div。
但似乎我尝试做的任何事情都不会导致 DOM 被修改为在 ajax 调用之前显示此 div。屏幕变为 "frozen",仅在执行 ajax 调用后才显示 div。
我已经尝试了 "thousands" 的方法,但似乎只有在修改 DOM 之后才 ajax 运行(显示 div) .
HTML
[...]
<body>
<div id="loadingDiv" style="display: none; width: 100%; height: 100%; background-color: #004000; position: absolute; z-index:10000;"></div>
[...]
javascript
[...]
$("#loadingDiv").css("display", "block");
var ajaxOp;
$.ajax({
type: someType,
url: someUrl,
data: someData,
dataType: someDataType,
async: false,
success: function (someArg) {
ajaxOp = someArg;
},
error: function (someArg0, someArg1, someArg2) {
// do something
}
});
return ajaxOp;
[...]
注意 I: 我正在使用 JQuery.
注意二:"ajaxOp"不能"undefined".
更新: 希望它有助于理解,应@Felipe Dutra Ferreira 的要求,我在下面的更新中对这个问题做了更多解释......
真实案例:我有一个包含多个遗留代码的应用程序,这些代码使用一个函数 libray js,该函数反过来进行 ajax 调用(我们称之为 "certainfunction")。我们正在尝试更新此应用程序,以便它在 ajax 调用期间显示 "loading screen"(而不仅仅是在这些调用期间显示 "lock" 和 UI)。因此,处理此问题的最简单方法是在 "certainfunction" 调用之后和 运行 调用 ajax 之前显示 "loading screen"。另请注意,"certainfunction" returns 来自 ajax 调用的输出和此输出将是 "undefined" 一旦此调用未同步执行,即代码只能在之后继续此 ajax 调用有一个输出。
我已经为你写了以下内容。
请查看我的 GITHUB
中的以下示例因为我有一个完整的示例,我已尽力帮助您。 在这里您将看到 Jquery 回调方法和承诺框架的使用,这似乎是您遇到的问题。请回复我,让我知道这是否是最终解决方案,因为我决心帮助您。
点击JSBin查看我的示例=> https://jsbin.com/xeloful/edit?html,output
<body onload="myFunction()" style="margin:0;"></body>
我想提请您注意... 如果您仍然需要帮助,请与我们联系...或者如果这没有帮助...
或者您可以 运行 Whosebug 上的代码片段。下面我使用 $(myFunction)
而不是 onload="myFunction()"
,这对于 jQuery 用户来说更为传统。点击下面的"Run Snippet"查看结果。
function showPage() {
document.getElementById("loader").style.display = "none";
document.getElementById("myDiv").style.display = "block";
};
function myFunction() {
//Showing a Div prior to call as promised...
$("#redSquare").fadeIn(3000).fadeOut(3000, function () {
//Making the following API Call that will receive a random email from a random user...
$.ajax({
url: 'https://randomuser.me/api/',
dataType: 'json',
success: showPage
}).done(function (res, req) {
//Spitting out information about the HTTP call made...
console.log(res);
console.log(req);
//Storing the email in the following variable...
var RandomEmail = res.results[0].email;
//Displaying the email in the console...
console.log(RandomEmail);
//Injecting the following email to the DOM
document.getElementById("randomEmail").innerHTML = RandomEmail;
});
});
}
//When the body loads, render this function as seen in the body HTML tag with the onload... This is the jQuery way to do it...
$(myFunction);
#redSquare {
display: none;
width: 100vw;
height: 100vh;
background-color: crimson;
}
/* Center the loader */
#loader {
position: absolute;
left: 50%;
top: 50%;
z-index: 1;
width: 150px;
height: 150px;
margin: -75px 0 0 -75px;
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Add animation to "page content" */
.animate-bottom {
position: relative;
-webkit-animation-name: animatebottom;
-webkit-animation-duration: 1s;
animation-name: animatebottom;
animation-duration: 1s
}
@-webkit-keyframes animatebottom {
from {
bottom: -100px;
opacity: 0
}
to {
bottom: 0px;
opacity: 1
}
}
@keyframes animatebottom {
from {
bottom: -100px;
opacity: 0
}
to {
bottom: 0;
opacity: 1
}
}
#myDiv {
display: none;
text-align: center;
}
#randomEmail {
color: white;
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="redSquare">
<!--Making this Appear for 3 Seconds prior to Ajax...-->
</div>
<div id="loader"></div>
<div style="display:none;" id="myDiv" class="animate-bottom">
<h2>Tada!</h2>
<p>Some text in my newly loaded page..</p>
<h1>
RandomEmail: <span id="randomEmail"></span>
</h1>
</div>
一个解决方法是使用下面的函数,当我们进行同步调用("ajax")时,允许在系统上显示一个"loading screen"。它可以很容易地适应遗留代码。
意识到 "ajax" 阻止了对 "DOM" 的修改,即使它是在本次调用之前执行的。只有在涉及之前的一些同步 ajax 调用的进程的第一次使用时,这种方法才有效。基本上,它会在执行所需的 function/method("appFunc")之前创建一个时间 window(50 毫秒)来更新 DOM。只有在需要在执行后立即使用同步 ajax 调用输出的情况下,使用此函数才有意义。
使用示例:<button type="button" onclick="opSyncLoading(login, [this.form])">
- 在这个例子中我们利用用户操作的"eventuality"创建一个时间window到线程并显示"loading screen"。请注意,"login" 函数不会 return 任何类型的输出。请注意,在 "login" 函数之后发生的所有事情都将以 "SYNC" 方式完成。
- 这个限制是因为 JS/DOM 只有一个 "thread" 来处理所有事情,也就是说,没有办法用 "sleep" 等待,例如,因为不存在任何类型的有效并行性。一种解决方案可能是使用 "web worker",但这超出了所提出问题的范围。
- 必须避免使用同步 "ajax" 调用,因为它会对 JS 的操作和 HTML 响应能力造成副作用,而且会被视为不良做法。它的使用应仅限于遗留代码或绝对必要的情况。
提示: 请注意,如果 "loading screen" 上有动画 gif,它将 "locked" 直到 "ajax" 调用完成,但是在某些现代浏览器中不会发生此问题。在极端情况下,如果图像加载到 iframe () 中,图像可能会保持 "animated"。
function opSyncLoading(appFunc, appFuncArgs) {
if (typeof appFuncArgs === "undefined" || appFuncArgs === "") {
appFuncArgs = [];
}
$("#loadingDiv").fadeIn(500, setTimeout(function () {
// NOTE: Passing unknown arguments in quantity and nature to a callback function. By Questor
// [Ref.: ]
appFunc.apply(this, appFuncArgs);
}, 50));
}
谢谢! =D