2017-10-05 70 views
0

說我有對象的數組具有異步方法:創建從對象異步瀑布

[ 
    { 
    partOne: function(input) { 
     // Do something async 
    }, 
    partTwo: function(result) { 
     // Do something w/ result of partOne 
    } 
    }, 
    { 
    partOne: function(resultOfPrevious) { 
     // Do something async 
    }, 
    partTwo: function(result) { 
     // Do something w/ result of partOne 
    } 
    }, 
    { 
    partOne: function(resultOfPrevious) { 
     // Do something async 
    }, 
    partTwo: function(result) { 
     // Do something w/ result of partOne 
    } 
    } 
] 

欲執行與我的輸入的第一個對象的partOne,結果傳遞(異步)到partTwo回調,然後將partTwo的結果作爲輸入傳遞給下一個對象的partOne,依此類推。該數組可能是一個或多個對象。我想知道執行這種代碼的最佳模式是什麼?

它有點類似於async.js的瀑布方法:https://caolan.github.io/async/docs.html#waterfall,但我想知道如何在沒有圖書館的情況下完成這項工作,並且可能使用更簡潔的代碼?

不確定異步/等待可以幫助嗎?

回答

2

另一種選擇,而不逢回調收集到的陣列,使用async/await

async function processWaterfallObject (data, input) { 
    let result = input 

    for (let entry of data) { 
    result = await entry.partOne(result) 
    result = await entry.partTwo(result) 
    } 

    return result 
} 

這裏假定您的data陣列中的功能是async或返回Promise


async/await目前由every major browser支持,並且提供node7.6.0

+0

非常好,很乾淨。 –

0

假設你在原來的問題給出對象的數組是一個名爲瀑布變量下

let collector = []; 
for (waterfallObj of waterfall) { 
    let tempArr = Object.values(waterfallObj);//get the functions out of the object 
    for (waterfallFunc of tempArr) { 
    collector.push(waterfallFunc); 
    } 
} 
//now you have your functions in order in collector 
function recursiveCallback(i) { 
    if (i>collector.length-1) { 
    return;//if there are no more to call then return 
    } 

    collector[i]().then(function(){ 
    recursiveCallback(i+1); 
    }); 
} 

如果你想下一個功能是與前面的函數值的東西,然後只需更改然後再(函數(passedValue然後使用passedValue在recursiveCallback呼叫內它

+0

你不會''從'collector'的任何地方'流行',所以'recursiveCallback'函數只會拋出'超出最大調用堆棧大小'。 –

+0

爲什麼我需要彈出?我在那裏有一個return語句,用於處理所有收集器函數 – Shard

+0

我的不好,你是完全正確的。我忽略了'i ... ...'部分。 –

1

下面是一個簡單的函數來調用每個異步函數的棧

function drain(stack, initialArg) { 
    stack.reduce(function (sectArg, section) { 
    return Object.keys(section).reduce(async function (arg, key) { 
     return await section[key].call(null,arg) 
    }, sectArg) 
    }, initialArg) 
} 

要使用它,確保你一疊返回一個值

var stack = [ 
    { 
    partOne: function(input) { 
     // Do something async 
     console.log('section one partOne', input) 
     return 'section one partOne output' 
    }, 
    partTwo: function(result) { 
     // Do something w/ result of partOne 
     console.log('section one partTwo', result) 
     return 'section one partTwo output' 
    } 
    }, 
    { 
    partOne: function(resultOfPrevious) { 
     // Do something async 
     console.log('section two partOne', resultOfPrevious) 
     return 'section two partOne output' 
    }, 
    partTwo: function(result) { 
     // Do something w/ result of partOne 
     console.log('section two partTwo', result) 
     return 'section two partTwo output' 
    } 
    }, 
    { 
    partOne: function(resultOfPrevious) { 
     // Do something async 
     console.log('section three partOne', resultOfPrevious) 
     return 'section three partOne output' 
    }, 
    partTwo: function(result) { 
     // Do something w/ result of partOne 
     console.log('section three partTwo', result) 
     return 'section three partTwo output' 
    } 
    } 
] 

所以,你可以調用各功能像

drain(stack, 'initialArg') 

看到這個jsfiddle:https://jsfiddle.net/kqj0rror/

+0

這沒有考慮到異步功能。 –

+0

我已經edittedto容納異步功能 – kharhys

+0

太棒了!我也注意到你正在用'this'調用'section [key]' - 我不確定這是否是一個好主意,它可能會導致代碼中出現很多意外的錯誤。也許你應該用'null'來代替? –