从promise块返回函数中的值
我试图编写一个函数(使用WebdriverJS lib)遍历元素列表,检查名称并构建与该名称相对应的xpath定位器。 我在这里简化了xpath定位器,所以不要留意。
我在这里遇到的问题是:1)调用这个函数返回undefined。 据我所知,这是因为return语句不在其位置上,但是:2)将它放在正确的地方,同步代码通常工作,不适用于异步promise,因此调用此函数将返回同样未定义,但是因为return语句在“driver.findElement”语句之前触发。
如果我想通过调用这个函数得到createdTask变量,我应该如何在这里使用return语句?
var findCreatedTask = function() {
var createdTask;
driver.findElements(By.xpath("//div[@id='Tasks_Tab']")).then(function(tasks) {
for (var index = 1; index <= tasks.length; index++) {
driver.findElement(By.xpath("//div[@id='Tasks_Tab'][" + index + "]//div[@class='task-title']")).getText().then(function(taskTitle) {
if (taskTitle == "testName") {
createdTask = "//div[@id='Tasks_Tab'][" + index + "]";
return createdTask;
}
});
}
});
};
您可以先用promise.map
获取所有文本,然后使用indexOf
获取位置:
var map = webdriver.promise.map;
var findCreatedTask = function() {
var elems = driver.findElements(By.xpath("//div[@id='Tasks_Tab']//div[@class='task-title']"));
return map(elems, elem => elem.getText()).then(titles => {
var position = titles.indexOf("testName") + 1;
return "//div[@id='Tasks_Tab'][" + position + "]";
});
}
在这里,我把它清理了一下。 如果有人遇到嵌套的promise,这实际上会返回一个错误:
var findCreatedTask = function() {
var Promise = require('bluebird');
var createdTask;
return driver.findElements(By.xpath("//div[@id='Tasks_Tab']"))
.then(function(tasks) {
return Promise.map(tasks, function(task){
return driver.findElement(By.xpath("//div[@id='Tasks_Tab'][" + index + "]//div[@class='task-title']")).getText()
}).then(function(taskTitles){
for (let i = 0; i < taskTitles.length; i++){
if(taskTitles[i] === 'testName'){
createdTask = "//div[@id='Tasks_Tab'][" + i + "]";
return createdTask;
}
}
});
});
};
你用它来称呼它
findCreatedTask.then(function(res){
//do your thing
}).catch(function(err){
console.error(err.stack);
});
您将无法从该函数返回所需的值,因为此函数返回时,该值尚未定义。
这不是你尝试在错误的地方返回值的问题,而是你尝试在错误的时间访问它的问题。
你有两种选择:你可以从这个函数返回一个promise,或者这个函数可以接受一个回调函数,当这个值可用时会被调用。
例子
这没有经过测试,但应该给你一个关于如何思考的想法。
诺言
有承诺的版本:
var findCreatedTask = function (callback) {
var createdTask;
return new Promise(function (resolve, reject) {
driver.findElements(By.xpath("//div[@id='Tasks_Tab']")).then(function(tasks) {
for (let index = 1; index <= tasks.length && !createdTask; index++) {
driver.findElement(By.xpath("//div[@id='Tasks_Tab'][" + index + "]//div[@class='task-title']")).getText().then(function(taskTitle) {
if (taskTitle == "testName") {
createdTask = "//div[@id='Tasks_Tab'][" + index + "]";
resolve(createdTask);
}
});
}
});
});
};
然后你用以下方式调用它:
findCreatedTask().then(function (createdTask) {
// you have your createdTask here
});
回电话
带回调的版本:
var findCreatedTask = function (callback) {
var createdTask;
driver.findElements(By.xpath("//div[@id='Tasks_Tab']")).then(function(tasks) {
for (let index = 1; index <= tasks.length && !createdTask; index++) {
driver.findElement(By.xpath("//div[@id='Tasks_Tab'][" + index + "]//div[@class='task-title']")).getText().then(function(taskTitle) {
if (taskTitle == "testName") {
createdTask = "//div[@id='Tasks_Tab'][" + index + "]";
callback(null, createdTask);
}
});
}
});
};
然后你用以下方式调用它:
findCreatedTask(function (err, createdTask) {
// you have your createdTask here
});
更多信息
您可以阅读其他一些解释承诺和回调如何工作的答案,如果您有兴趣知道其中的内容: