在数组的排序函数中实现异步/等待javascript

问题描述:

我想在量角器ElementArrayFinder上实现排序方法。众所周知,所有量角器方法都会返回承诺。 所以我的排序方法有一个条件,这取决于承诺解决方案。 我为了我使用async/await节点插件,使其与node.js的版本低于6 (此处插件:https://www.npmjs.com/package/asyncawait)兼容在数组的排序函数中实现异步/等待javascript

这里我的代码,其中thisArrayElementFinder

var asyncCompare = async(function(a, b) { 
    let x = await (a.getText()); 
    let y = await (b.getText()); 
    console.log(x.localeCompare(y)); 
    return x.localeCompare(y); 
}); 

var sortTheArray = async(function(arrayOfElementFinders) { 
    return await (arrayOfElementFinders.sort(asyncCompare)); 
}); 

this.then((elements) => { 
    let arrayOfElementFinders = [elements[0], elements[1], elements[2]]; 
    let sortedArray = sortTheArray(arrayOfElementFinders); 
    console.log('array sorted'); 
}); 

不幸的是,时间执行不是我所期望的。打印:array sorted发生在比较x.localeCompare(y)的打印之前。 任何想法我做错了什么?任何想法如何实现我的目标?

非常感谢您的帮助

+0

Array.prototype.sort是一个同步函数。 – tibetty

sort不采取异步回调。它期望一个数值作为返回值,而不是一个承诺;它确实返回一个数组而不是承诺。这是没有办法的(尽管可以实现一个自定义的异步排序算法 - 甚至是一个并行算法)。

但无论如何,这是非常低效的。在每个排序步骤中执行比较值的异步读取操作都会很慢 - 并且它会多次读取每个元素的相同值。不要这样做。相反,使用Schwartzian transform来获取要排序的值,然后进行排序(同步),然后使用结果。

你应该做

const elements = await this; 
const arrayOfElementFinders = elements.slice(0, 3); // or Array.from? 
const comparableArray = await Promise.all(arrayOfElementFinders.map(async x => [await x.getText(), x])); 
comparableArray.sort((a, b) => +(a[0] > b[0]) || -(a[0] < b[0])); 
const sortedArray = comparableArray.map(x => x[1]); 
console.log('array sorted'); 
+0

感谢您的回复Bergi。所以实际上你的建议是使用异步代码手动检索我的比较值(例如通过承诺),然后使用同步排序函数返回这些我之前计算的值? – quirimmo

+0

@quirimmo是的,正是 – Bergi

+0

非常感谢你的位置和你的答案,真的很好,真的很有用。不幸的是我无法得到它的工作。两个主要问题:1)目前我从上面的代码中取回3'undefined':'[undefined,undefined,undefined]'。 2)我想摆脱'async/await'并只使用承诺,也许我用来实现的第三方库也是第一个问题的原因。请任何想法吗?再次感谢 – quirimmo

这岂不是V6之前支持的承诺?

我不喜欢混合命令await与功能promise抽象。你不能这样做吗?

Promise.all([Promise.resolve(10), Promise.resolve(4), Promise.resolve(7)]) 
 
     .then(r => r.sort((a,b) => a-b)) 
 
     .then(s => console.log(s));

ANS飞溅.catch()阶段需要?

+1

嗨@Redu感谢您的回复。 是的,它确实支持V6中的ES6承诺,但我不记得自哪个版本节点支持es6承诺。 Btw使用量角器你应该使用他们的承诺本地实现:'protractor.promise' 我试图避免使用ES6承诺,即使比由量角器提供的标准更好 – quirimmo