【问题标题】:jQuery chaining and cascading then's and when'sjQuery 链接和级联 then 和 when 的
【发布时间】:2015-02-16 11:42:00
【问题描述】:

我目前有一个巨大的 if-then-else 循环在我面前,它首先从 web 服务获取多个 cantinas。然后它获取所有可用的饭菜(每个菜单)和所有可用的配菜(每个菜单)。然后,它会检查每餐以及每餐的所有添加剂并汇总它们。

最后我有多个菜单,包括正餐、配菜及其所有添加剂。

下面的流程图展示了这个过程:

我想美化代码并想使用 jQuery 的 Promise - 但我不知道该怎么做,因为我必须在 when 之后堆叠 then (至少我认为,也许我必须resolve?)。以下是我最好的尝试:

//this totally does not work at all, but you get the idea what I want to do
Menus.getCantinas()
       .when(Menus.getMeals(cantinas), Menus.getSides(cantinas)) //when doesn't exist here, neither does cantinas
         .then(Menus.getAdditives(meals, sides) //also throws errors as meals and sides does not exist
           .done(function(cantinas, meals, sides, additives) { //more errors for the people
             Menus.cantinas = cantinas;
             Menus.meals = meals;
             Menus.sides = sides;
             Menus.additives = additives;

             //... some html stuff to build the menus
           });

请务必查看以下代码 sn-p 以获得更多解释性代码。

window.Menus = {
	cantinas = {},
	meals = {},
	sides = {},
	additives = {},
	callWebservice: function (listname, filter)
    {
        if (filter && filter != '')
            data['$filter'] = filter;

        return jQuery.ajax({
            url: '/_api/web/lists/getbytitle(\'' + listname + '\')/items',
            data: data,
            dataType: 'json'
        });
    },

	getCantinas: function() {
		return Menus.callWebservice("Cantinas", "");
	},
	
	getMeals: function(cantinas) {
		var filterString;
		for (var i = 0; i < cantinas.length; i++) {
			if (i == 0) {
				filterstring = "ID eq " + cantinas[i];
			}
			else {
				filterstring += " or ID eq " + cantinas[i]
			}
		}
		return Menus.callWebservice("Meals", filterString);
	},
	
	
	getSides: function(cantinas) {
		//see above function for filterstuff
		return Menus.callWebservice("Sides", filterString);
	},
	
	getAdditives: function(meals, sides) {
		for (var i = 0; i < meals.length; i++) {
			if (i == 0 && !meals) {
				filterstring = "ID eq " + meals[i];
			}
			else {
				filterstring += " or ID eq " + meals[i]
			}
		}
		
		for (var i = 0; i < sides.length; i++) {
			if (i == 0 && !sides) {
				filterstring = "ID eq " + sides[i];
			}
			else {
				filterstring += " or ID eq " + sides[i]
			}
		}
		return Menus.callWebservice("Additives", "");
	}
	Init: function() {
		//this totally does not work at all, but you get the idea what I want to do
		Menus.getCantinas()
			   .when(Menus.getMeals(cantinas), Menus.getSides(cantinas))
			     .then(Menus.getAdditives(meals, sides)
			       .done(function(cantinas, meals, sides, additives){
				     Menus.cantinas = cantinas;
					 Menus.meals = meals;
					 Menus.sides = sides;
					 Menus.additives = additives;
					 
					 //... some html stuff to build the menus
				   });
	}
}
Menus.Init()

我希望我说得通?如何利用承诺和级联参数从一个到下一个,基本上如何使上述语句起作用并为我提供包含多餐、配菜和添加剂的多个菜单。

【问题讨论】:

  • 您是否从所有异步操作返回承诺,然后在异步操作完成时解决这些承诺?只有 Promise 有 .then() 方法。例如,Menus.callWebservice() 是否返回承诺?
  • 您可以在代码 sn-p 中看到缩短的代码 - 我正在重新调整来自 callWebservice 的 jQuery ajax 对象
  • 另外,你不能做类似.then(Menus.getAdditives(meals, sides))的事情。您必须传递像 .then(function() {return Menus.getAdditives(meals, sides)}) 这样的函数引用。只有第二种形式实际上在等待承诺。
  • 另外,jQuery 中没有 promise.when() 方法。有一个$.when(),您可以将其包装在您自己的函数中,然后传递给.then()

标签: javascript jquery promise jquery-deferred chaining


【解决方案1】:

就像 cmets 所说的那样,$.when 是一个免费功能。如果我们使用thenable 链接,我们可以在这里得到非常干净的语法。

Menus.getCantinas().then(function(cantinas){ // `then` is how we chain promises
    Menus.cantinas = cantinas;
    // if we need to aggregate more than one promise, we `$.when`
    return $.when(Menus.getMeals(cantinas), Menus.getSides(cantinas));
}).then(function(meals, sides){ // in jQuery `then` can take multiple arguments
    Menus.sides = sides; // we can fill closure arguments here
    Menus.meals = meals;
    return Menus.getAdditives(meals, sides); // again we chain
}).then(function(additives){
    Menus.additives = additives;
    return Menus; // we can also return non promises and chain on them if we want
}).done(function(){ // done terminates a chain generally.
     // edit HTML here
});

【讨论】:

  • 简直太美了。感谢您的解释!
  • 很高兴我能帮上忙 :) 如果您希望我在此示例中澄清任何其他内容,请告诉我。总的来说,我发现承诺执行模型树非常好。
  • 教程/文档不包括从函数内部返回链(如这里return Menus.getAdditives(...)以及像这样使用$.when。现在对我来说很有意义,只是在任何地方都找不到像这样的 “高级” 示例。
  • @DennisG 我想这主要是因为您使用的是我个人don't appreciate very much 的 jQuery 承诺。通常更高级的教程主题是关于原生 ES6 Promise 或 Promise 库,如 Bluebird 或 Q。Promise 很棒,不仅用于聚合,还用于抛出安全和部分的逻辑抽象 - jQuery 的 Promise,虽然比回调更好,但缺少一些理想的属性我认为较新的承诺实现有。 (inb4 对不起 jfriend00 的咆哮)
  • 知识pr0n。 ES6 在 IE8 环境中不是一个选项。其他库可能会更好,但是如果 jQuery 做得很好,为什么还要使用另一个库。出于我的目的,这可以解决问题,但我会阅读您的链接帖子以了解缺点。
猜你喜欢
  • 1970-01-01
  • 2012-12-24
  • 1970-01-01
  • 1970-01-01
  • 2021-11-02
  • 2015-09-08
  • 1970-01-01
  • 2014-08-24
  • 1970-01-01
相关资源
最近更新 更多