Promise .then() 不等待 Promise 链中前一个 Promise 的 Resolve()

Promise .then() Not Waiting For Resolve() Of the Previous Promise In A Promise Chain

我对 Promises 的概念很陌生,但我读到这是一种通过称为 Promise 链接的方式使函数一个接一个地执行的有效方法。

下面的 //运行 ON CLCK: CREATE TABLES 代码基本上进行了两次 AJAX 调用,“创建数据库表”和“检查数据库表”,因此当我按下按钮时网页,后台会创建数据库表,然后检查它们是否存在。

但它并不像预期的那样 运行。在许多情况下,从控制台日志中可以看出,第二个函数 运行s (or) 首先完成。无论如何,这不应该发生在链中。

看起来第二个函数没有等待第一个函数的解析。

请注意,我的函数有参数,因此我无法避免在 then() 中调用它们时不带括号,正如其他一些文章所推荐的那样。

$(document).ready(function() {

    /*PAGE VARS*/
    var mainAdmStgChkTblSrvltMsg_elm = document.getElementById('mainAdmStgChkTblSrvltMsg');
    var mainAdmStgCrDelTblSrvltMsg_elm = document.getElementById('mainAdmStgCrDelTblSrvltMsg');
    var mainAdmStgCrTblBtn_elm = document.getElementById('mainAdmStgCrTblBtn');

    /*FN DEF: CHECK TABLES*/
    var chkTbl = function(tblNm) {
        return new Promise(function(resolve, reject) {
            $.ajax({
                type: 'GET',
                url: '../../../../../../app/TblSrvlt',
                data: {
                    getType: 'chkTbl',
                    tblNm: tblNm
                },
                success: function(data) {
                    var srvltMsg = data.srvltMsg;
                    var srvltSuccess = data.srvltSuccess;
                    mainAdmStgChkTblSrvltMsg_elm.textContent = srvltMsg;
                    if (srvltSuccess === true) {
                        mainAdmStgChkTblSrvltMsg_elm.setAttribute('class', 'text-success');
                    } else {
                        mainAdmStgChkTblSrvltMsg_elm.setAttribute('class', 'text-danger');
                    }
                    /*RETURN RESOLVE FOR PROMISE CHAIN*/
                    console.log("chkTbl");
                    resolve();
                }
            });
        });
    };

    /*FN DEF: CREATE TABLES*/
    var crTbl = function(tblNm) {
        return new Promise(function(resolve, reject) {
            $.ajax({
                type: 'POST',
                url: '../../../../../../app/TblSrvlt',
                data: {
                    postType: 'crTbl',
                    tblNm: tblNm
                },
                success: function(data) {
                    var srvltMsg = data.srvltMsg;
                    var srvltSuccess = data.srvltSuccess;
                    mainAdmStgCrDelTblSrvltMsg_elm.textContent = srvltMsg;
                    if (srvltSuccess === true) {
                        mainAdmStgCrDelTblSrvltMsg_elm.setAttribute('class', 'text-success');
                    } else {
                        mainAdmStgCrDelTblSrvltMsg_elm.setAttribute('class', 'text-danger');
                    }
                    /*RETURN RESOLVE FOR PROMISE CHAIN*/
                    console.log("crTbl");
                    resolve();
                }
            });
        });
    };

    /*RUN ON CLCK: CREATE TABLES*/
    $(document).on('click', '#' + mainAdmStgCrTblBtn_elm.id, function() {
        Promise.resolve()
            .then(crTbl("chairs"))
            .then(chkTbl("chairs"))
            .catch();
    });
});

您必须将函数引用传递给 .then(),以便它稍后可以调用您的函数。相反,您立即调用这些函数并将它们的 return 值传递给 .then() 这就是为什么它们会立即被调用而不是等待先前的承诺来解决。

改变这个:

/*RUN ON CLCK: CREATE TABLES*/
$(document).on('click', '#' + mainAdmStgCrTblBtn_elm.id, function() {
    Promise.resolve()
        .then(crTbl("chairs"))
        .then(chkTbl("chairs"))
        .catch();
});

对此:

/*RUN ON CLCK: CREATE TABLES*/
$(document).on('click', '#' + mainAdmStgCrTblBtn_elm.id, function() {
    Promise.resolve()
        .then(function() {return crTbl("chairs")})
        .then(function() {return chkTbl("chairs")})
        .catch(function(err) { console.log(err)});
});

而且,您实际上不需要链开头的 Promise.resolve()

/*RUN ON CLCK: CREATE TABLES*/
$(document).on('click', '#' + mainAdmStgCrTblBtn_elm.id, function() {
     crTbl("chairs")
        .then(function() {return chkTbl("chairs")})
        .catch(function(err) { console.log(err)});
});