2017-08-13 65 views
4

我想在量角器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

回答

4

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

0

這豈不是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