[英]How to Break out of Jquery's Each Loop WITH PROMISE
My question is addition to: How to break out of jQuery each Loop 我的问题是除了: 如何突破每个循环的jQuery
I need to exit from the jquery $.each() but in this case I cannot return FALSE, since the exit condition is firing a function that is going to resolve a defer. 我需要退出jquery $ .each()但在这种情况下我不能返回FALSE,因为退出条件是触发一个将解决延迟的函数。 So I need to exit the each, but with a promise.
所以我需要退出每一个,但有一个承诺。
function KillLayer(id) {
var defer = $.Deferred();
$.each(vm.get("DeviceData"), function (idx, item) {
if (item.Type == id) {
vm.DeviceData.splice(idx, 1); // remove the item from the list
removeLayer(defer, id) // delete it from the PouchDB (IDB) database (async)
return defer.promise();
}
});
defer.resolve(); // layer was not found, so just resolve & return
return defer.promise();
}
try like this. 试试这样。
objDP = null; // To get Deferred’s Promise object.
$.each(vm.get("DeviceData"), function (idx, item) {
if (item.Type == id) {
vm.DeviceData.splice(idx, 1); // remove the item from the list
removeLayer(defer, id) // delete it from the PouchDB (IDB) database (async)
objDP = defer.promise();
return false;
}
});
As you have discovered, you can't return from KillLayer()
inside its each()
loop because a return statement in that context has a different meaning. 正如您所发现的那样,您无法在其
each()
循环内从KillLayer()
返回,因为该上下文中的return语句具有不同的含义。
Here's a couple of different approaches : 这里有几种不同的方法:
1: Use a boolean flag to signal whether or not a deletion took place and treat the Deferred accordingly. 1:使用布尔标志来表示是否发生了删除,并相应地处理延迟。
function KillLayer(id) {
var defer = $.Deferred(), deleted = false;
$.each(vm.get("DeviceData"), function (idx, item) {
if (item.Type == id) {
vm.DeviceData.splice(idx, 1); // remove the item from the list
removeLayer(defer, id); // delete it from the PouchDB (IDB) database (async)
deleted = true;
return false;//break from each() loop
}
});
return deleted ? defer.promise() : defer().resolve().promise();//return either a promise of deletion or a ready-resolved promise.
}
2: (If you have control over removeLayer()
) Arrange for removeLayer()
to generate and return its own promise, rather than passing in a Deferred. 2 :(如果你可以控制
removeLayer()
)安排removeLayer()
生成并返回自己的promise,而不是传递Deferred。 This will allow you to simplify KillLayer()
as follows: 这将允许您简化
KillLayer()
,如下所示:
function KillLayer(id) {
var deletionPromise;
$.each(vm.get("DeviceData"), function (idx, item) {
if (item.Type == id) {
vm.DeviceData.splice(idx, 1); // remove the item from the list
deletionPromise = removeLayer(id); // delete it from the PouchDB (IDB) database (async), and receive back a promise
return false;//break from each() loop
}
});
return deletionPromise || $.Deferred().resolve().promise(); //return either a promise of deletion from the DB, or a ready-resolved promise
}
Although there's only one line difference, I would contend that the second appraoch is cleaner. 虽然只有一个线差异,但我认为第二个appraoch更清洁。 As
removeLayer()
performs an asynchronous activity, it should really return a promise of its own, and not rely on a Deferred being passed to it. 由于
removeLayer()
执行异步活动,它应该真正返回自己的promise,而不是依赖于传递给它的Deferred。
This will not break from the each loop, but it will make the following iterations do nothing: 这不会从每个循环中断,但它会使以下迭代不执行任何操作:
function KillLayer(id) {
var defer = $.Deferred();
var result = null;
$.each(vm.get("DeviceData"), function (idx, item) {
if (!result && item.Type == id) {
vm.DeviceData.splice(idx, 1); // remove the item from the list
removeLayer(defer, id) // delete it from the PouchDB (IDB) database (async)
result = defer.promise();
}
});
return result || defer.resolve();
}
I came up with Beetroots answer #1 independently. 我想出了Beetroots独立回答#1。 Firstly I realize that looping through an $each() and removing items from javascript array that your are looping is a great way for errors.
首先,我意识到循环遍历$ each()并从javascript数组中删除您正在循环的项目是一种很好的错误方法。 I really should do something like this:
我真的应该这样做:
$.each(clone(vm.get("DeviceData")), function (idx, item)` {
where the clone function is defined as: 其中clone函数定义为:
function clone(obj) {
return jQuery.extend({}, obj);
}
function deepClone(obj) {
return jQuery.extend(true, {}, obj);
}
But in my case, I don't need that extra protection, so I just updated my solution as follows: 但在我的情况下,我不需要额外的保护,所以我刚刚更新了我的解决方案如下:
function KillLayer(id) {
var defer = $.Deferred();
var found = false;
$.each(vm.get("DeviceData"), function (idx, item) {
if (item.Type == id) {
vm.DeviceData.splice(idx, 1);
Compare();
dbManifest.LayerInfo = vm.DeviceData.toJSON();
removeLayer(defer, id)
found = true;
return false;
}
});
if (!found) defer.resolve(); // layer was not found, so just resolve & return
return defer.promise();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.