使用Promises和AJAX调用顺序执行

时间:2014-11-10 16:41:15

标签: javascript jquery ajax promise

我简化了代码,只关注重要部分并描述我的问题。

我有一个带有AJAX请求的函数返回一个ID。

function addProposal(){
    var name_en = $("#name_en").val();
    var use_en = $("#use_en").val();
    var desc_en = $("#desc_en").val();  

    $.ajax({
        type:'POST',
        url:'http://localhost/index.php?option=com_test&task=addProposal&format=raw',
        data:{  user_id: user_id,
            name_en: name_en,
            use_en: use_en,
            desc_en: desc_en
        },
        beforeSend:function(){
            $("#loading_modal").modal("show");
        },
        complete:function(){
            $("#loading_modal").modal("hide");
        },
        done:function(id){
            //------I get the ID here, when it's done----
            alert(id); 
            idNewProposal=id;
        }
   });
}

当用户点击按钮

时,我会调用此函数
$(document).ready(function()
{
    //...

    $(document).on('click', '#btn_add_valid', function() {
         addProposal();
    });

     //...
 }

当用户点击此按钮时,我有另一个附加到事件的功能,以便上传文件(参见下面的代码)。 我的问题是我需要在执行上传之前在之前的AJAX调用中生成的Id(第#34行; data.submit")

$(document).ready(function()

{
    //....

    //Function to upload file

    $('#file-upload').fileupload({
         dataType: 'json',
         autoUpload: false,
         paramName: 'files[]',
         maxNumberOfFiles:1,
         add: function (e, data) {
            //---The callback "add" is triggered each time that one file is selected
            // I did not write all the code here but you have to know that I make some test 
            //for each selection under this callback (size and type of file).
            //So if the user select a file which not match with the constraints, 
            //the input stay empty and an error message is displayed. 

            //--However I want to start the upload after the click on the button
             $(document).on('click', '#btn_add_valid', function() {
                 data.formData = { id: idNewProposal}; //------I need the ID here----
                 data.submit(); //--The upload start Here (after the click on the button, all the files are sent)
             });

         },
         done: function (e, data) {
                 $("#loading_file").modal("hide");
                 $("#validation_modal").modal("show");
         },
         progressall: function (e, data) {
                 var progress = parseInt(data.loaded / data.total * 100, 10);
                 $('#upload-file .bar').css(
                     'width',
                      progress + '%'
                 );
         },
         fail: function (e, data) {
                 alert('Error');
                 $("#loading_file").modal("hide");
         }
  });

}

总结一下:点击按钮后我需要先执行addProposal()函数,当它完成后,我需要启动上传(data.submit in $(' #file -upload'。)文件上传()) 显然,有一种方法可以通过" promises"来管理这类问题。在Jquery,但我无法理解如何在这种情况下使用它。

非常感谢任何能够帮助我解决这个问题的人。

3 个答案:

答案 0 :(得分:1)

让我们使用承诺。

function addProposal(){
    var name_en = ...
    return $.ajax({ // note the return here, the function now returns a promise
        ...
        beforeSend:function(){
            $("#loading_modal").modal("show");
        },
        complete:function(){
            $("#loading_modal").modal("hide");
        }
   });
}

现在,我们想在功能完成时启动上传:

addProposal().then(function(result){
    $(..).fileupload(...) // access addProposal's data in `result`
})

现在,您可能希望在样本中的两次不同点击上执行此操作,或者只需拥有add:

     add: function (e, data) {
       // ...
       $(document).on('click', '#btn_add_valid', function() {
         addProposal().then(function(res){
           data.formData = { id: res};
           data.submit(); 
         });
       });
     },...

每次调用add:时调用addProposal,如果你想总是调用addProposal一次,你可以将它缓存在另一个函数中:

var p = null;
function cachedProposal(){
    return p || (p = addProposal());
}

这是管理调用addProposal的两种最简单的方法,如果你的逻辑不同 - 适应。

请注意,addProposal应该使用参数而不是使用全局变量。

答案 1 :(得分:0)

将功能放在一起:

done:function(id){


            //------I get the ID here, when it's done----
            alert(id); 
            idNewProposal=id;

在功能之前进行onclick检查,仍然包裹在一起,必要时再包装另一个onclick元素

我不确定这个onclick应该返回什么,但以太方式,只是做一个if检查,如果它正确运行另一个函数...

     $(document).on('click', '#btn_add_valid', function() {
             addProposal().;
      if(idNewProposal != //or equals to something){
 proposalCheck(); // call the function
    function proposalCheck() {
                     data.formData = { id: idNewProposal}; //------I need the ID here----
                     data.submit(); //--The upload start Here (after the click on the button, all the files are sent)


         $('#file-upload').fileupload({
                 dataType: 'json',
                 autoUpload: false,
                 paramName: 'files[]',
                 maxNumberOfFiles:1,
                 add: function (e, data) {
     ...



         }
    });
    });
};

答案 2 :(得分:0)

基于本杰明提出的解决方案。我写了以下函数:

function addProposal(){
    //console.log("Execute AddProposal");
    var name_en = $("#name_en").val();
    var use_en = $("#use_en").val();
    var desc_en = $("#desc_en").val();  

    return $.ajax({
        type:'POST',
        url:'http://localhost/index.php?option=com_test&task=addProposal&format=raw',
        data:{  user_id: user_id,
                name_en: name_en,
                use_en: use_en,
                desc_en: desc_en,
        },
        beforeSend:function(response){
                $("#loading_modal").modal("show");
                //console.log("AddProposal - BEFORESEND");
        },
        complete:function(response){
                $("#loading_modal").modal("hide");
               //console.log("AddProposal - COMPLETE");

        },
    });
}

function cachedProposal(){
    //console.log("Execute cachedProposal");
    return p || (p = addProposal());
}

在主函数" $(document).ready(function()"中,我写了这段代码

$(document).ready(function()
{
   p = null;
   //....

   $('#file-upload').fileupload({
        dataType: 'json',
        autoUpload: false,
        paramName: 'files[]',
        maxNumberOfFiles:1,
        add: function (e, data) {
            var uploadErrors = [];
            var acceptImgTypes = /^image\/(gif|jpe?g|png)$/i;
            var acceptDocTypes = /^application\/(pdf|msword|vnd.openxmlformats-officedocument.wordprocessingml.document)$|^text\/plain$/i;

            //console.log("ADD FILE: "+ data.files[0].name);

            if (data.fileInput[0].id=="file-img"){
                if (data.originalFiles[0]['type'] && !acceptImgTypes.test(data.originalFiles[0]['type'])) {
                    uploadErrors.push('Not an accepted file type');
                }
                if (data.originalFiles[0]['size'] && data.originalFiles[0]['size'] > 4000000) {
                    uploadErrors.push('File size is too big');
                }
            }else{
                if (data.originalFiles[0]['type'] && !acceptDocTypes.test(data.originalFiles[0]['type'])) {
                    uploadErrors.push('Not an accepted file type');
                }
                if (data.originalFiles[0]['size'] && data.originalFiles[0]['size'] > 10000000) {
                    uploadErrors.push('File size is too big');
                }
            }

            if (uploadErrors.length > 0) {
                    alert(uploadErrors.join("\n"));
            } else {
                if (data.fileInput[0].id=="file-img"){
                    $("#txt-file-img").val(data.files[0].name);
                }else{
                    $("#txt-file-doc").val(data.files[0].name);
                }

                 $(document).on('click', '#btn_add_valid', function() {
                    cachedProposal().then(function(res){
                        //console.log("cachedProposal-Promise : id="+res.id);
                        data.formData = {id: res.id};
                        data.submit(); 
                        //-----$("#loading_file").modal("show");
                    });
                 });

             }
        },
        done: function (e, data) {
            //-----$("#loading_file").modal("hide");
            $("#validation_modal").modal("show");
        },
        progressall: function (e, data) {
            var progress = parseInt(data.loaded / data.total * 100, 10);
            $('#upload-file .bar').css(
                'width',
                progress + '%'
            );
            $('#file-percentage').text(
                    progress + '%'
            );
        },
        fail: function (e, data) {
                alert('Error');
                //-----$("#loading_file").modal("hide");
        }
   });


    $(document).on('click', '#btn_add_valid', function() {
        //console.log("---CLICK ON SUBMIT BUTTON---");
        var $img =$("#txt-file-img").val();
        var $doc =$("#txt-file-doc").val();
        if (($img == '') && ($doc == '')){
           // console.log("Submit - NO FILES");
            addProposal();
            $("#validation_modal").modal("show");
        }
    });
});

跟踪和结果

场景:没有选择文件

跟踪:

---CLICK ON SUBMIT BUTTON---
Submit - NO FILES
Execute AddProposal
Add Proposal - BEFORESEND
Add Proposal - COMPLETE

结果:

1数据库中的条目 - 没有FOLDER&没有上传的文件 - >行


选择一个文件(图像文件输入)

ADD FILE: capture.jpg
---CLICK ON SUBMIT BUTTON---
Execute cachedProposal
Execute AddProposal
AddProposal - BEFORESEND
cachedProposal-Promise : id=76
AddProposal - COMPLETE
ERROR too much recursion //???

1数据库中的条目(ID = 76)AND

使用名称76创建的1个FOLDER以及上传的img文件 - >行


选择一个文件(输入doc文件)

ADD FILE: test.pdf
---CLICK ON SUBMIT BUTTON---
Execute cachedProposal
Execute AddProposal
AddProposal - BEFORESEND
AddProposal - COMPLETE
cachedProposal-Promise : id=79
AddProposal - COMPLETE"
ERROR too much recursion //???

1数据库中的条目(ID = 79)AND

使用名称79和上传的doc文件创建的1个FOLDER - >行


选择了两个文件(每个输入一个)

ADD FILE: capture.jpg
ADD FILE: test.pdf
---CLICK ON SUBMIT BUTTON---
Execute cachedProposal
Execute AddProposal
AddProposal - BEFORESEND
Execute cachedProposal
cachedProposal-Promise : id=80
AddProposal - COMPLETE
ERROR too much recursion //???

1数据库中的条目(ID = 80)AND

使用名称80创建的1个文件夹,并且上传了两个文件 - >行


一切正常,除了我在控制台中有这个奇怪的错误信息" ERROR太多的递归"。每次上传文件时都会显示它。有人知道它来自哪里?

编辑:如果我用$(" #loading_file")评论这些行.modal(...);消息消失了!看到带注释的代码(// -----)。 我不明白为什么?