2016-04-08 30 views
0

我已经通过并尝试了几个同步调用函数的例子,但它似乎并没有为我工作。我使用外部句柄模板来生成一个加载了数据的'parent'html元素,然后在加载之后,我想从我创建的'child'模板(使用它们自己的数据)添加html。这两个函数调用都调用相同的函数,但仅传递不同的模板/数据。以下是我对此的代码 - 任何帮助表示赞赏。谢谢!不能让这两个函数同步调用

var loadSimpleCollection = function(templateFile, dataFile, containerSelector) { 

    var deferred = $.Deferred(); 

    $.get(templateFile, function(text) { 

    // Extract HTML from the template file 
    var raw_template = text; 

    // Compile that into an handlebars template 
    var template = Handlebars.compile(raw_template); 

    // Retrieve the container where the data will be displayed 
    var container = $(containerSelector); 

    // Fetch collection data from JSON file 
    $.getJSON(dataFile, function(data, status, xhr) { 
     $.each(data,function(index,element){ 
     var html = template(element); 
     container.append(html); 
     }); 
    }); 

    }); 

    return deferred.promise(); 

} 

loadSimpleCollection('template1.hbs', 'data1.json', '#parent-div').then(loadSimpleCollection('template1.hbs', 'data2.json', '#child-div')); 
+0

可能要包装你'then'表达,否则它被立即调用。例如'.then(function(){loadSimpleCollection(...)})' –

+0

你需要在'container.append(html);' –

回答

0

有你的代码中的多个问题:

  1. 你是不是永远解决您的递延
  2. 没有必要创建自己的诺言 - 你可以回到你已经有了相当的承诺比使用the promise anti-pattern
  3. 你打电话.then()错误,如果你正在做其他承诺的东西,你的代码甚至不会等待承诺。

我建议这样的:

var loadSimpleCollection = function(templateFile, dataFile, containerSelector) { 

    return $.get(templateFile).then(function(text) { 

    // Compile that into an handlebars template 
    var template = Handlebars.compile(text); 

    // Retrieve the container where the data will be displayed 
    var container = $(containerSelector); 

    // Fetch collection data from JSON file 
    return $.getJSON(dataFile).then(function(data, status, xhr) { 
     $.each(data,function(index,element){ 
     var html = template(element); 
     container.append(html); 
     }); 
     return container; 
    }); 

    }); 

} 

loadSimpleCollection('template1.hbs', 'data1.json', '#parent-div').then(function() { 
    loadSimpleCollection('template1.hbs', 'data2.json', '#child-div') 
}); 

变化:

你已经有
  1. 回报的承诺,而不是创造新的deferreds。避免承诺反模式。
  2. 为您的ajax调用使用promise。
  3. 链的两个loadSimpleCollection()内部异步操作,以便它们将被连接在一起,当两者都做
  4. 传递一个函数引用.then()因此它可以被称为后,不立即执行主叫方可以知道。

即使这一切,似乎奇怪加载和编译相同template1.hbs两次。您当然可以加载一次,编译它,然后将其用于多个其他操作。

你也许可以使代码的运行速度是这样的:

var p1 = $.get('template1.hbs'); 
var p2 = $.getJSON('data1.json'); 
var p3 = $.getJSON('data2.json'); 
$.when(p1, p2, p3).then(function(t, d1, d2) { 
    var template = Handlebars.compile(t[0]); 
    var container = $('#parent-div'); 
    $.each(d1[0], function(index, element) { 
     container.append(template(element)); 
    }); 
    container = $('#child-div'); 
    $.each(d2[0], function(index, element) { 
     container.append(template(element)); 
    }); 
}); 
+0

完成后解析返回的承诺'deferred.resolve()'!像魅力一样工作 - 感谢jfriend00! – Heath

+0

@Heath - 我添加了一个更快的选项,只加载模板一次,并行执行所有ajax调用。 – jfriend00

+0

@Heath - 由于您看起来可能是新手,您是否知道当您的问题得到解答时,您可以通过选择最佳答案旁边的绿色复选标记来向社区表明这一点?而且,在堆栈溢出的情况下,这也会为您赢得一些声望点。 – jfriend00