语境
对于一个系统,有一个进程使用事务与 Web SQL 同步来自外部 API(总共 6 个表)的信息,这个过程是使用按钮手动完成的SINCRONIZAR
,在进程运行时,有必要阻止他们登录或重新同步它们,使两个按钮都被锁定:
实际过程
我试图注释掉不相关的部分,以使其更容易理解。
通过使用setInterval()和clearInterval()我设法等待多个异步事件的完成:
// URLs para consumir cada tabla del API externo
// baseAPI viene desde otro archivo
var cultivosAPI = baseAPI + "/api/cultivos/";
var usuariosAPI = baseAPI + "/api/usuarios/";
var terminalesAPI = baseAPI + "/api/terminales/";
var personalAPI = baseAPI + "/api/personal/";
var laboresAPI = baseAPI + "/api/labores/";
var plantasAPI = baseAPI + "/api/plantas/";
// Objeto para saber el estado de la sincronización de cada
// tabla
var updateStates = {};
// ID inicial del intervalo usado en la función setInterval()
var intervalId = 0;
$(document).ready(function(){
// ...
// Boton ACTUALIZAR, antes de sincronizar se asegura
// de que exista conexión con el servidor
$("#updateBtn").on("click", testConnection);
// ...
});
function testConnection() {
$.ajax(
baseAPI
).done(function (data) {
// Si todo está bien, sincronizar las tablas
updateTables();
}).fail(function() {
// ...
});
}
function updateTables() {
// ...
// Hash para conocer el resultado de actualización de cada tabla,
// es la variable definidida arriba
updateStates = {
"cultivo": null,
"labor": null,
"personal": null,
"planta": null,
"terminal": null,
"usuario": null
};
// Deshabilitar botones
$("#loginBtn").prop("disabled", true);
$("#updateBtn").prop("disabled", true);
// ...
// ***************************************************
// Esta es la parte asíncrona en donde se llama el API
// de cada tabla
// ***************************************************
// Insertar cultivos
$.getJSON(cultivosAPI, {
format: "json"
}).done(function (data) {
db.transaction(function(tx) {
// SQL y otras cosas
});
}).fail(function(data) {
// Marcamos la tabla como incompleta
updateStates["cultivo"] = false;
// ...
});
// Insertar personal
$.getJSON(personalAPI, {
format: "json"
}).done(function (data) {
db.transaction(function(tx) {
// SQL y otras cosas
});
}).fail(function(data) {
// Marcamos la tabla como incompleta
updateStates["personal"] = false;
// ...
});
// Insertar terminales
$.getJSON(terminalesAPI, {
format: "json"
}).done(function (data) {
db.transaction(function(tx) {
// SQL y otras cosas
});
}).fail(function(data) {
// Marcamos la tabla como incompleta
updateStates["terminal"] = false;
// ...
});
// Insertar usuarios
$.getJSON(usuariosAPI, {
format: "json"
}).done(function (data) {
db.transaction(function(tx) {
// SQL y otras cosas
});
}).fail(function(data) {
// Marcamos la tabla como incompleta
updateStates["usuario"] = false;
// ...
});
// Insertar labores
$.getJSON(laboresAPI, {
format: "json"
}).done(function (data) {
db.transaction(function(tx) {
// SQL y otras cosas
});
}).fail(function(data) {
// Marcamos la tabla como incompleta
updateStates["labor"] = false;
// ...
});
// Insertar plantas
$.getJSON(plantasAPI, {
format: "json"
}).done(function (data) {
db.transaction(function(tx) {
// SQL y otras cosas
});
}).fail(function(data) {
// Marcamos la tabla como incompleta
updateStates["planta"] = false;
// ...
});
// Esperar que finalicen las actualizaciones para habilitar
// los botones, valida cada segundo
intervalId = setInterval(updateIsFinished, 1000);
}
function updateIsFinished() {
// El proceso puede haber terminado sin terminar de actualizar por algún
// error encontrado
var updated = true;
var finished = true;
// Iteramos cada estado de la tabla, si la tabla tiene un valor
// false es porque hubo un error en la llamada AJAX, si tiene un
// valor null es porque el AJAX aun no finaliza
for (table in updateStates) {
if (updateStates[table] == false) {
updated = false;
}
if (updateStates[table] == null) {
finished = false;
}
}
if (updated || finished) {
// Limpiar el intervalo
clearInterval(intervalId);
// Resetear valores globales
updateStates = {};
intervalId = 0;
// Habilitar botones
if (updated) {
$("#loginBtn").prop("disabled", false);
$("#updateBtn").prop("disabled", false);
} else if (finished) {
$("#updateBtn").prop("disabled", false);
}
}
}
问
虽然它有效,但我觉得可能有更好的方法来实现它,而无需每秒钟检查一次。我尝试使用jQuery.when()但它不起作用。
如何等待异步事件而不必检查每个特定时间间隔?
如果你使用 jQuery,你最好的选择是
$.when
.该函数
when
接收一个Promise对象列表并返回另一个Promise,该 Promise 将在每个项目被解析时被解析。作为Promise,您可以done
像fail
往常一样链接方法。一个例子:
在这种情况下
done
,如果所有请求都成功并且fail
至少有一个请求失败,则执行它。对于您的具体问题,经过一点重构:),我会尝试像这样解决它:
如果每个端点的代码在每种情况下都不同,那么您可以将它放在端点数组中:
接着
想到的解决方案之一是使用jQuery 的Ajaxstart和Ajaxstop,它们可以让您知道请求何时运行以及何时完成。对于您的代码,它将是这样的:
这样,您将知道请求何时准备就绪以及登录按钮何时释放。就我而言,我只使用它发出 1 个请求,而不是多个请求,但我认为它仍然可以工作,或者您应该修改的最多是使请求嵌套。