2016-12-07 65 views
3

我有一個承諾,返回功能,做一些異步的東西,我們稱之爲functionToRepeat()Javascript的承諾:鏈同樣的承諾n次,然後做別的事

我正在嘗試編寫函數repeatFunction(amount),以便它將啓動承諾,等待完成,再次啓動,等待完成等等。這個repeatFunction(amount)也應該是可以接受的,以便我可以在執行完其他東西之後進行鏈接。

這裏是我的嘗試:

function functionToRepeat(){ 
    let action = new Promise(function(resolve,reject){ 
    setTimeout(function(){ 
     console.log("resolved!"); 
     resolve()} 
    ,1000); 
    }) 
    return action 
} 

function repeatFunction(amount) { 
    if(amount==0){ 
    return Promise.resolve(); 
    } 
    return functionToRepeat().then(function(){ 
    repeatFunction(amount-1); 
    }); 
} 

repeatFunction(5).then(function(){ 
console.log("DONE!"); 
}) 

這成功鏈我的諾言(或因此它接縫,在控制檯中我得到一個「解決了!」每秒)。 但是.then()我試圖在我的repeatFunction(5)在第一個承諾結束後發生鏈接,而不是在所有5個結束之後!

因此,在我的控制檯中,我得到:

已解決! 完成! 解決! 解決! 解決! 解決!

我在做什麼錯,我應該改變什麼?

回答

2

我認爲你是幾乎沒有,但你必須在你的函數,然後再塊返回repeatFunction重複。

return functionToRepeat().then(function(){ 
    return repeatFunction(amount-1); 
    }); 
} 

如果你有一個then,但不返回任何東西,那麼它只是解決上的承諾。這就是發生了什麼事。

1

你缺少一個return當你調用repeatFunction(amount-1)

function functionToRepeat(){ 
    let action = new Promise(function(resolve,reject){ 
    setTimeout(function(){ 
     console.log("resolved!"); 
     resolve()} 
    ,1000); 
    }) 
    return action 
} 

function repeatFunction(amount) { 
    if(amount==0){ 
    return Promise.resolve(); 
    } 
    return functionToRepeat().then(function(){ 
    return repeatFunction(amount-1); // Added return 
    }); 
} 

repeatFunction(5).then(function(){ 
console.log("DONE!"); 
}) 

https://plnkr.co/edit/93T6B4QkBv0mYS4xPw0a?p=preview

-1
let loopP = (n, f, ...args) => { 
    let p = f(...args); 
    p.then(res => { 
    if (n - 1) { 
     loopP(n - 1, f, res); 
    } 
    }); 
}; 

哪裏n是迭代次數,f是守信用返回函數被調用。每次對f的連續呼叫在解析時都會傳遞前一次呼叫的結果。

例如...

let addOneP = i => { 
    console.log(i + 1); 
    return Promise.resolve(i + 1); 
}; 

loopP(5, addOneP, 0); 
// logs: 
// 1 
// 2 
// 3 
// 4 
// 5 
+0

這真的很不錯,但_...這個'repeatFunction(amount)'也應該是可以的... __ –

3

如何簡單:

function oneSecond() { 
    return new Promise(function (resolve, reject) { 
    setTimeout(function() { 
     console.log("tick"); 
     resolve(); 
    }, 1000); 
    }); 
} 

repeat(oneSecond, 5).then(function() { 
    console.log("done"); 
}); 

這個輸出產生超過5秒:

function repeat(func, times) { 
    var promise = Promise.resolve(); 
    while (times-- > 0) promise = promise.then(func); 
    return promise; 
} 

這個測試時

tick 
tick 
tick 
tick 
tick 
done 
1

您可以使用async/await和簡單的while循環。這讓你在Asyncland允許你繼續鏈接重複功能後

async function asyncRepeat (f, n) { 
    while (n-- > 0) 
    await f() 
} 

asyncRepeat(functionToRepeat, 5).then(() => { 
    console.log('done') 
}) 

// some value 
// some value 
// some value 
// some value 
// some value 
// done 

這是垃圾壽。您僅限於使用副作用函數f參數asyncRepeat。因此,登錄到控制檯是可行的,但是如果你真的想用這個價值做一些事情呢?

這裏有一個更新asyncRepeat,使您可以線程的值通過你的輸入功能(asyncDouble在這個例子中)重複申請

(重要變化大膽

async function asyncRepeat (f, n, x) { 
    while (n-- > 0) 
    x =await f(x) 
    return x 
} 

function asyncDouble (x) { 
    return new Promise(function (resolve, reject) { 
    setTimeout(() => { 
     console.log('x is currently: %d', x) 
     resolve(x * 2) // resolve an actual value 
    }, 1000) 
    }) 
} 

asyncRepeat(asyncDouble, 5, 2).then(result => { 
    console.log('result: %d', result) 
}) 

// x is currently: 2 
// x is currently: 4 
// x is currently: 8 
// x is currently: 16 
// x is currently: 32 
// result: 64
0

你可能會發現relign對這類事情有用。這裏是你用relign series和relign setTimeout編寫的例子。

const fnToRepeat =() => 
    relign.setTimeout(() => console.log("resolved!"), 1000); 

relign.series((new Array(5)).fill(fnToRepeat)) 
    .then(() => console.log('done'));