我有一个网络测试代码,在找到该项目后,我不想迭代其余部分。 此代码迭代到所有项目并最终返回。 如何解决这个问题,因为在每一次我都没有休息!
isItemPresent: function (name) {
var def = Q.defer();
Trace.add("Checking the " + name + " inside the menu");
var count = 0, total = 0, stop = false;
var listObj = element(by.id(this.MENU_ID)).all(by.tagName("div"));
listObj.count().then(function (nr) {
total = nr;
listObj.each(func);
});
var _this = this;
var func = function (element) {
element.getAttribute('class').then(function (classes) {
count++;
if (classes.indexOf(name) !== -1 && !stop) {
stop = true;
element.getAttribute('id').then(function (value) {
_this._isItemVisible('', value).then(function (opt) {
value = value.match(/(\d+)/g);
if (opt.success) {
// console.log('------- BREAK --------');
def.resolve({success: true, msg: {index: value[0]}});
Trace.add("Menu item: " + name + " was found in the main menu.");
} else {
def.resolve({success: false, msg: {index: value[0]}});
Trace.add("Menu item: " + name + " was not found in the main menu.");
}
});
});
} else if (count === total && stop === true) {
def.resolve({success: false, msg: {index: 0}});
Trace.add("Menu item: " + name + " was not found in the main menu.");
stop = true;
}
});
};
return def.promise;
};
答案 0 :(得分:1)
有各种解决方案,其中没有一个特别明显。 This is the best presentation/discussion that I know of
您可能会考虑this answer中给出的非常简洁的Bluebird解决方案,但是,坚持使用Q
,这是基于"循环"的解决方案。在同一个答案的解决方案。
isItemPresent: function (name) {
var _this = this,
listObj = element(by.id(this.MENU_ID)).all(by.tagName("div")),
list = [];
//Map listObj to the Array `list`, providing a convenient .reduce() method.
//If listObj has a `.toArray()` method or `.map()` method, then use that in preference.
listObj.each(function(element) {
list.push(element);
});
// To make func() useful it must return a promise :
// * fulfilled for success - forcing a "break"
// * rejected for failure - allowing "continue"
function func(element) {
return element.getAttribute('class').then(function(classes) {
if (classes.indexOf(name) === -1) {
return Q.reject('class "' + name + '" not found');//"continue"
} else {
return element.getAttribute('id').then(function(value) {
_this._isItemVisible('', value).then(function(opt) {
if(opt.success) {
return Q(value.match(/(\d+)/g)[0]);//"break".
} else {
return Q.reject('class "' + name + '" not visible');//"continue"
}
});
});
}
});
};
// Master routine
return list.reduce(function(previous, element) {
return previous.catch(function(error) {
console.log(error || 'list length is zero'); //optional
return func(element);
});
}, Q.reject(null)).catch(function(error) {
return Q.reject(-1);//for example
});
};
<强>解释强>
主例程构建一个.catch()
链,其中包含被拒绝的承诺和
只要func()
继续返回被拒绝的承诺,catch(...)
回调就会确保再次为下一个元素调用func()
。
如果func()
永远不会命中opt.success
,则主例程返回返回给它的最后一个被拒绝的承诺(如果list
长度为零,则返回种子承诺)。
如果/当func()
点击opt.success
时,会返回一个履行了所需值的承诺,并且有效跳过主例程的承诺链的其余部分,因为没有成功处理程序导致它不这样做,并且主例程返回返回给它的已履行的承诺。
最终.catch()
只是一个例子。您可能希望做一些不同的事情 - 无论何处调用isItemPresent(name)
,最适合处理失败的事情。