【问题标题】:Implement async/await in sort function of arrays javascript在数组javascript的排序函数中实现async/await
【发布时间】:2018-01-21 12:12:48
【问题描述】:

我正在尝试在量角器ElementArrayFinder 上实现排序方法。众所周知,所有量角器方法都返回承诺。 所以我的排序方法有一个取决于承诺解决的条件。 我正在为async/await 使用节点插件,以使其与低于 6 的 node.js 版本兼容。 (这里的插件:https://www.npmjs.com/package/asyncawait

这是我的代码,其中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) 的打印之前。 知道我在做什么错吗?知道如何实现我的目标吗?

非常感谢您的帮助

【问题讨论】:

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

标签: javascript sorting promise async-await protractor


【解决方案1】:

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

【讨论】:

  • 感谢您的回复,Bergi。所以实际上你的建议是使用异步代码(例如通过承诺)手动检索我的比较值,然后使用同步排序函数返回我之前计算的这些值?
  • @quirimmo 是的,就是这样
  • 非常感谢您的位置和回答,非常好,非常有用。不幸的是,我无法让它工作。两个主要问题:1)目前我从上面的代码中返回 3 undefined[ undefined, undefined, undefined ]。 2)我想摆脱async/await,只使用promises,也许我用于实现的第三方库也是第一个问题的原因。请问有什么想法吗?再次非常感谢
  • 这是我迄今为止所做的,用承诺来改变它。很抱歉格式错误,但在 cmets 中很糟糕。 this.then((elements) =&gt; { const arrayOfElementFinders = elements.slice(0, 3); // or Array.from? const comparableArray = Promise.all(arrayOfElementFinders.map(async((x) =&gt; [await(x.getText(), x)]))); comparableArray.then((arr) =&gt; { arr.sort((a, b) =&gt; +(a[0] &gt; b[0]) || -(a[0] &lt; b[0])); const sortedArray = arr.map(x =&gt; x[1]); console.log(sortedArray); }); });
  • undefineds 发生在哪里,在arrayOfElementFinders(可能我的slice() 呼叫不起作用),或comparableArraysortedArray?关于async/await,您当然可以用then() 回调替换它们,但是当它们可用时,我认为没有任何理由这样做。
【解决方案2】:

V6 之前不支持 Promise 吗?

我不喜欢将命令式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 splatter .catch() 需要的阶段?

【讨论】:

  • 嗨@Redu 感谢您的回复。是的,它确实支持 V6 中的 ES6 Promises,但我不记得因为哪个版本节点支持 es6 Promises。顺便说一句,使用量角器你“应该”使用他们的原生承诺实现:protractor.promise我试图避免使用 ES6 承诺,即使比量角器提供的标准承诺要好得多
猜你喜欢
  • 1970-01-01
  • 2017-05-05
  • 2016-01-22
  • 2021-08-06
  • 2019-04-24
  • 1970-01-01
  • 2021-11-05
相关资源
最近更新 更多