2016-12-25 250 views
8

我試着寫一個返回的異步函數的所有結果的功能,並執行推到一個數組的回調和記錄每一個異步函數的結果。JS:獲取異步函數內部函數參數和執行回調

由於把所有的菜時,他們都做了服務員。 我不明白如何獲得應該作爲結果返回的子參數。任務,我不工作的解決方案的代碼如下:

任務:

var dishOne = function(child) { 
    setTimeout(function() { 
     child('soup'); 
    }, 1000); 
}; 

var dishTwo = function(child) { 
    setTimeout(function() { 
     child('dessert'); 
    }, 1500); 
}; 
waiter([dishOne, dishTwo], function(results) { 
    console.log(results); // console output = ['soup', 'dessert'] 
}); 

我不工作的解決方案:

function child(arg) { 
    this.arr.push(arg) 
} 

function waiter(funcArray, doneAll) { 
    var result = { 
     arr: [] 
    }; 
    let i = 0; 
    const x = child.bind(result) 
    funcArray.forEach(function(f) { 
     f(x) 
     i++; 
     if(i == 2) { 
     doneAll(result.arr) 
     } 
    }); 
} 

回答

5

問題是這樣的部分:

funcArray.forEach(function(f) { 
    f(x) 
    i++; 
    if(i == 2) { 
    doneAll(result.arr) 
    } 
}); 

這是一個同步功能,所以當你檢查if(i == 2)時,你基本上檢查,你已經調用了所有的同步功能,但他們還沒有返回任何東西,所以你知道的是,這些功能已被調用,但result.arr尚未填充。

您必須將doneAll(result.arr)表達式移入child回調函數中,然後它將由異步函數調用,因爲它返回結果。

Simpliest解決方案,我能想到的是寫你child

function child(arg) { 
    if (this.arr.push(arg) === this.allCount) this.doneAll(this.arr); 
} 

,並在您waiter功能增強的結果對象

var result = { 
    arr: [] 
    , allCount: funcArray.length 
    , doneAll: doneAll 
}; 

這應工作,但有一個缺點 - 結果的位置不保持funcArray的功能位置,結果的位置由異步函數的時間排序,乾脆先解決將需要第一個結果等。如果這是一個問題,你也必須通過指數您child功能存儲導致在結果陣列珍貴的位置,然後通過arr.length檢查是行不通的,因爲JS數組返回長度爲最高指數+ 1,因此,如果您的最後一個funcArray將首先完成,這將填補最後一個索引和result.arr長度將等於this.allCount,所以爲了保持結果的順序一樣funcArray,你將需要存儲返回結果的數量另一個號碼,增加與每一個新的結果,這個數字,這個數字比較allCount

,或者降低allCount像這樣

function child(idx, arg) { 
    this.arr[idx] = arg; 
    if (--this.allCount === 0) this.doneAll(this.arr); 
} 

和修改waiter功能

function waiter(funcArray, doneAll) { 
    const result = { 
     arr: [] 
     , allCount: funcArray.length 
     , doneAll: doneAll 
    }; 

    funcArray.forEach(function(f, i) { 
     f(child.bind(result, i)); 
    }); 
} 
0

爲什麼不Promise

function dishOne() { 
    return new Promise(function(resolve, reject) { 
     setTimeout(function() { resolve('soup') }, 1000) 
    }) 
} 

function dishTwo() { 
    return new Promise(function(resolve, reject) { 
     setTimeout(function() { resolve('dessert') }, 1500) 
    }) 
} 

waiter功能:

function waiter(dishes, callback) { 
    return Promise.all(dishes).then(callback) 
} 

而且你可以使用它像這樣

waiter([dishOne(), dishTwo()], function(results) { 
    // Invoked when all dishes are done 
    console.log(results) // ['soup', dessert'] 
}) 

要容易理解得多。對?

+0

哎呀,對不起,我只是錯誤地理解了這個問題 – Octopitus