javascript - promesas - ¿Cambia el diálogo de jQuery asíncrono para que sea síncrono?
jquery load php (6)
Aquí hay algunas ideas: lo que realmente quiere es bloquear su evento asíncrono para que parezca sincronización. Aquí hay algunos enlaces:
Espero que esto te ayude más!
Actualmente, estoy trabajando para reemplazar "alerta" / "confirmar" con el diálogo de jquery.
Pero la mayoría de los códigos heredados están escritos de manera asincrónica, lo que dificulta su modificación. ¿Hay alguna manera de hacer que el diálogo de jquery funcione de forma síncrona? (no use el bucle ni la función de devolución de llamada)
For example:
function run()
{
var result = confirm("yes or no");
alert( result );
//more codes here
}
En este ejemplo, la alerta y otros códigos se ejecutarán después de la elección del usuario.
Si usamos el diálogo jquery var result = $ dialog.open () Continuará ejecutando la alerta, que es asincrónica.
Actualmente, mi solución es usar la función de devolución de llamada en la función OK | Cancelar. Por ejemplo:
OK: function ()
{
$dialog.close();
alert("yes");
//more codes here
}
Este método funciona, pero es difícil hacer que todos los códigos síncronos se vuelvan asíncronos, lo que requiere muchos cambios (consulte el siguiente ejemplo). Así que estoy buscando el diálogo jQuery sincrónico, ¿es posible?
Por ejemplo: (Los códigos reales son mucho más complicados que el siguiente ejemplo)
function f1()
{
if ( confirm("hello") ) f2();
alert("no");
}
function f2()
{
if( confirm("world") ) f3();
alert("no");
}
function f3()
{
return confirm("!") ;
}
Otro ejemplo:
vendorObject.on(''some-event'', function() {
if(confirm("Do you really want to do that?")) {
return true;
}
else {
return false; // cancel the event
}
});
... aquí el objeto vendedor dispara un evento, que debe ser cancelado si el usuario lo confirma. El evento solo se puede cancelar si el controlador de eventos devuelve false
- sincrónicamente.
La respuesta corta es no, no podrá mantener su código sincrónico. Este es el por qué:
- Para que esto sea sincrónico, la secuencia de comandos actualmente en ejecución tendría que esperar a que el usuario ingrese y luego continuar.
- Si bien hay un script que se está ejecutando actualmente, el usuario no puede interactuar con la interfaz de usuario. De hecho, la IU ni siquiera se actualiza hasta después de que la secuencia de comandos termina de ejecutarse.
- Si la secuencia de comandos no puede continuar hasta que el usuario proporcione información y el usuario no pueda proporcionar información hasta que la secuencia de comandos finalice, lo más parecido que podrá encontrar es un navegador bloqueado.
Para ilustrar este comportamiento, depure su código y establezca un punto de interrupción en la línea siguiendo una línea que cambie la UI:
$("body").css("backgroundColor", "red");
var x = 1; // break on this line
Tenga en cuenta que el fondo de su página aún no es rojo. No cambiará a rojo hasta que reanude la ejecución y el script termine de ejecutarse. Tampoco puede hacer clic en ningún enlace en su página mientras tiene la ejecución del script en pausa con su depurador.
Hay una excepción a esta regla para alert()
y confirm()
. Estos son controles del navegador y se tratan de forma diferente a los elementos reales de la IU de la página web.
La buena noticia es que realmente no debería ser muy difícil convertir tu código. Presumiblemente, su código actualmente se ve más o menos así:
if (confirm("continue?")) {
// several lines of code if yes
}
else {
// several lines of code if no
}
// several lines of code finally
Su versión asíncrona podría crear una función ifConfirm(text, yesFn, noFn, finallyFn)
y su código se vería muy ifConfirm(text, yesFn, noFn, finallyFn)
:
ifConfirm("continue?", function () {
// several lines of code if yes
},
function () {
// several lines of code if no
},
function () {
// several lines of code finally
});
Editar: en respuesta al ejemplo adicional que agregó a su pregunta, desafortunadamente ese código tendrá que ser refactorizado. Simplemente no es posible tener diálogos de confirmación personalizados sincrónicos. Para usar un cuadro de diálogo de confirmación personalizado en el escenario donde un evento necesita continuar o cancelarse, simplemente deberá cancelar el evento e imitar el evento en la yesFn
llamada yesFn
.
Por ejemplo, un enlace:
$("a[href]").click(function (e) {
e.preventDefault();
var link = this.href;
ifConfirm("Are you sure you want to leave this awesome page?", function () {
location.href = link;
});
});
O bien, una forma:
$("form").submit(function (e) {
e.preventDefault();
var form = this;
ifConfirm("Are you sure you''re ready to submit this form?", function () {
form.submit();
});
});
No estoy exactamente seguro de cuál es la motivación detrás de no usar devoluciones de llamada, por lo que es difícil juzgar qué solución podría satisfacer sus requisitos, pero otra forma de retrasar la ejecución es a través del objeto "diferido" de jQuery.
http://api.jquery.com/category/deferred-object/
Puede configurar una función que abra el cuadro de diálogo jquery y agregue el código que "espera" para que se cierre el cuadro de diálogo. Esto termina trabajando de una manera bastante similar a una devolución de llamada en el caso que ha presentado, pero aquí hay un ejemplo:
function confirm () {
var defer = $.Deferred();
$(''<div>Do you want to continue?</div>'').dialog({
autoOpen: true,
close: function () {
$(this).dialog(''destroy'');
},
position: [''left'', ''top''],
title: ''Continue?'',
buttons: {
"Yes": function() {
defer.resolve("yes"); //on Yes click, end deferred state successfully with yes value
$( this ).dialog( "close" );
},
"No": function() {
defer.resolve("no"); //on No click end deferred successfully with no value
$( this ).dialog( "close" );
}
}
});
return defer.promise(); //important to return the deferred promise
}
$(document).ready(function () {
$(''#prod_btn'').click(function () {
confirm().then(function (answer) {//then will run if Yes or No is clicked
alert(''run all my code on '' + answer);
});
});
});
Aquí está trabajando en jsFiddle: http://jsfiddle.net/FJMuJ/
No, no se puede sincronizar nada en Javascript (la alerta infringe las reglas, de hecho). Javascript está construido con "un solo subproceso, asincrónico" en el núcleo.
Sin embargo, lo que puede hacer es desactivar la funcionalidad de la página subyacente (similar a lightbox) para que no se active ningún evento desde la página hasta que no realice la acción de diálogo, ya sea que esté OK o Cancelar. Pensé que esto no ayuda a que tu código de sincronización funcione. Tienes que reescribir.
Para responder la pregunta más específica de David Whiteman, así es como estoy implementando una devolución de datos "diferida" para un evento LinkButton Click. Básicamente, solo estoy impidiendo el comportamiento predeterminado y activando la devolución de datos manualmente cuando los comentarios de los usuarios están disponibles.
function MyClientClickHandler(event, confirmationMessage, yesText, noText) {
// My LinkButtons are created dynamically, so I compute the caller''s ID
var elementName = event.srcElement.id.replace(/_/g, ''$'');
// I don''t want the event to be fired immediately because I want to add a parameter based on user''s input
event.preventDefault();
$(''<p>'' + confirmationMessage + ''</p>'').dialog({
buttons: [
{
text: yesText,
click: function () {
$(this).dialog("close");
// Now I''m ready to fire the postback
__doPostBack(elementName, ''Y'');
}
},
{
text: noText,
click: function () {
$(this).dialog("close");
// In my case, I need a postback when the user presses "no" as well
__doPostBack(elementName, ''N'');
}
}
]
});
}
Realmente no veo por qué te opones a usar devoluciones de llamada de Jquery para lograr el comportamiento en tu ejemplo. Definitivamente tendrá que volver a escribir un código, pero algo como:
function f1() {
$( "#testdiv" ).dialog({
modal: true,
buttons: {
"OK": function() {
$( this ).dialog( "close" );
f2();
},
Cancel: function() {
$( this ).dialog( "close" );
alert(''no'');
}
}
});
}
function f2() {
$( "#testdiv2" ).dialog({
modal: true,
buttons: {
"OK": function() {
$( this ).dialog( "close" );
f3();
},
Cancel: function() {
$( this ).dialog( "close" );
alert(''no'');
}
}
});
}
function f3() {
$( "#testdiv3" ).dialog({
modal: true,
buttons: {
"OK": function() {
$( this ).dialog( "close" );
},
Cancel: function() {
$( this ).dialog( "close" );
}
}
});
}
<div id="testdiv" title="Hello"/>
<div id="testdiv2" title="World"/>
<div id="testdiv3" title="!"/>