在.each函数中等待$ .ajax结果

时间:2018-08-10 22:50:13

标签: javascript jquery

我具有搜索具有特定类的每个元素的功能:

$("#stepSurveyCtnId .questionCtnClass").each(function () {}

在每个步骤中,我检查问题是否属于客户类型:

var type = $(this).children().data("question-type");

var isCustomerQuestion = false;

switch (type) {
    case "Name":
    case "Email":
        isCustomerQuestion = true;
        break;
}

如果是客户类型,我将从数据库中获取客户表的下一个ID:

  if(isCustomerQuestion) {
      if (customerId == -1) {
          $.ajax({
              method: "POST",
              url: urlCustomerCreate, 
              success: function (ajaxData) {
                  customerId = ajaxData.NumericValue;
              }
          });
      } 
  }

问题在于,在.each()函数的第二次迭代中,customerId仍为-1,例如应为1305。

似乎执行不会在$ .ajax调用中停止,或者迭代同时执行,并且第二个迭代没有从第一次迭代接收到customerId。

5 个答案:

答案 0 :(得分:5)

我仍然不确定100%是否为您构建所有结构,但这是处理JavaScript异步性的一种方法(改编自@ShubHam的答案)

public class InstructionsController implements EventHandler<ActionEvent>, Initializable {

    @FXML
    private Button about, constants, professionPerks, teamCilantro, mainMenu, exit;

    @FXML
    private AnchorPane background;

    @FXML
    private TextArea text;

    Main main = new Main();

    private List<String> name;
    private List<String> desc;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        Instructions instructions = new Instructions();
        name = instructions.getListName();
        desc = instructions.getListDesc();
    }

    @FXML
    public void handle(ActionEvent event) {
        Button selected = (Button) event.getSource();
        Stage stage = (Stage) selected.getScene().getWindow();

        if (selected == about)

        if(selected == mainMenu) 
            main.switchScene("fxml/Title.fxml", stage);

        if(selected == exit) 
            stage.close();
    }
}

这只会在触发成功回调后继续进行下一次迭代。

答案 1 :(得分:3)

将逻辑放在一个函数(例如函数1)中,并在另一个函数中进行ajax调用。

从函数1调用ajax函数。在内部成功调用具有所需参数的函数1

更新(添加示例):

var x=['a','b','c']
var elm=document.getElementById('demo')
x.forEach(function(temp){
elm.innerHTML=elm.innerHTML+temp
})
<div id='demo'></div>

可以将其转换为新逻辑

var x=['a','b','c']
function sethtml(temp,length,maxlength){
  //here ajax call can be placed
  var elm=document.getElementById('demo')
  elm.innerHTML=elm.innerHTML+temp
  //inside success function of ajax
  traverse(length+1,maxlength)
}

function traverse(length,maxlength){
  if(length>=maxlength)
  {
    //all calls done next steps to perform
  }else{
    sethtml(x[length],length,maxlength)
  }
}

traverse(0,x.length)
<div id='demo'></div>

建议在Jamie-Day中考虑以下建议:检查您的逻辑以寻求改进的范围。通常可以避免针对每种情况访问db结果(理想情况下,应避免访问db结果,以获得更好的用户体验)

答案 2 :(得分:2)

更改您的Ajax代码。添加“ async:false”,以便ajax旁边的每个代码都将等待ajax结果

self.send_email

答案 3 :(得分:1)

AJAX中的第一个A代表“异步”,这意味着ajax调用将被执行,而不会等待调用完成。这样,我们可以让用户与页面上的其他元素进行交互,并提供良好的用户体验。

如果通过将async选项设置为false来使AJAX调用异步,那么浏览器将等待ajax调用完成,并且用户将无法与元素进行交互,直到调用完成。随着呼叫数量的增加,该阻塞时间将增加。

我建议您找到一个比这更好的选择。

答案 4 :(得分:1)

首先,您需要异步思考。 应该从成功函数中调用需要在ajax之后运行的代码。您还希望添加error函数来处理服务器错误。

第二,为了提高速度和带宽,我通过将所有ID合并到一个AJAX请求中,将AJAX调用的数量减少到一个。 它需要在服务器端进行更改,而您没有提供服务器端,所以我将服务器端留给您。

// Prepare ajax call
var customerData = [];
var customerCreateData = [];
$("#stepSurveyCtnId .questionCtnClass").each(function () {
    var type = $(this).children().data("question-type");
    var isCustomerQuestion = false;
    switch (type) {
        case "Name":
        case "Email":
            isCustomerQuestion = true;
            break;
    }

    // Set customerId and customerCreateData

    if(isCustomerQuestion) {
        if (customerId == -1) {
            customerCreateData.push(customerCreateData);
        }
    }
}); // end each

if (customerCreateData.length) {
      $.ajax({
              method: "POST",
              url: urlCustomerCreate,
              data: customerCreateData,
              success: function (ajaxData) {
                  customerData = ajaxData.customerData;
                  doAmazingThingsWithCustomers(customerData);
              },
              error: function(jqXHR, textStatus, errorThrown) {
                  alert('Server error: ' + errorThrown);
              }
          });
}