从promise块返回函数中的值

我正在尝试编写一个函数(使用WebdriverJS lib)遍历元素列表,检查名称并构build与该名称相对应的xpath定位器。 我在这里简化了xpath定位器,所以不要留意。

我在这里遇到的问题是:1)调用这个函数返回undefined。 据我所知,这是因为return语句不在其位置上,而是:2)将它放在一个正常的同步代码正常工作的地方,不适用于asynchronouspromise,因此调用此函数将返回同样未定义,但是因为return语句在“driver.findElement”语句之前触发。

如果我想通过调用这个函数得到createdTaskvariables,我应该如何在这里使用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 + "]"; }); } 

在这里,我把它清理了一下。 这实际上会返回一个错误,如果有经验的嵌套承诺:

 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); }); 

您将无法从此函数返回所需的值,因为此函数返回时,该值尚未定义。

这不是你尝试在错误的地方返回值的问题,而是你试图在错误的时间访问它。

你有两个select:你可以从这个函数返回一个promise,或者这个函数可以接受一个在值可用的时候被调用的callback函数。

例子

这不是testing,但应该给你一个想法如何思考。

诺言

有承诺的版本:

 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 }); 

回电话

带callback的版本:

 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 }); 

更多信息

您可以阅读其他一些答案,解释承诺和callback如何工作,如果你有兴趣知道这个答案:

  • 有关如何使用callback和承诺的详细说明
  • 有关如何在复杂的请求处理程序中使用promise的说明
  • 关于AJAX请求的例子,解释了什么是承诺
  • 解释callback,承诺以及如何访问asynchronous返回的数据