2015-10-21 66 views
2

我怎麼能一個接一個地發出承諾?如何解決承諾一個接一個?

waitFor(t),是一個函數,它返回一個在t時間後解析的promise。我希望能夠與做的是:

waitFor(1000) Then when finished, console.log('Finished wait of 1000 millis') then 
waitFor(2000) Then when finished, console.log('Finished wait of 2000 millis') then 
waitFor(3000) Then when finished, console.log('Finished wait of 3000 millis') 

這裏是我的嘗試:

waitFor(1000).then(function(resolve, reject) { 
    console.log(resolve); 
}).then(waitFor(2000).then(function(resolve, reject) { 
    console.log(resolve); 
})).then(waitFor(3000).then(function(resolve, reject) { 
    console.log(resolve); 
})); 

可惜這console.logs語句層出不窮每1秒,這意味着承諾所有人都立即致電。

我設法與像這樣的回調修正這個問題,然而這使得一切非常難看:

waitFor(1000).then(function(resolve, reject) { 
    console.log(resolve+' @ '+(new Date().getSeconds())); 
    waitFor(2000).then(function(resolve, reject) { 
     console.log(resolve+' @ '+(new Date().getSeconds())); 
     waitFor(3000).then(function(resolve, reject) { 
      console.log(resolve+' @ '+(new Date().getSeconds())); 
     }); 
    }); 
}); 

那麼應該怎麼辦這與使得它的工作,但沒有使用難看回調地獄的承諾?

不希望的結果:http://jsfiddle.net/nxjd563r/1/

期望的結果:http://jsfiddle.net/4xxps2cg/

+0

這可能幫助 - http://tech.transferwise.com/making-serial-xhr-calls-in-angularjs/ – FrailWords

+0

我甚至不使用angularjs .... –

+0

我指出這個博客有一個想法 - 去尋找一個遞歸函數,它將貫穿你的一系列承諾。 – FrailWords

回答

3

我發現你的解決方案。

您需要讓每個then返回一個新的承諾,以便下一個then可以在解決前一個問題後作出反應。

waitFor(1000).then(function(result) { 
    $('#result').append(result+' @ '+(new Date().getSeconds())+'<br>'); 
    return waitFor(2000); 
}).then(function(result) { 
    $('#result').append(result+' @ '+(new Date().getSeconds())+'<br>'); 
    return waitFor(3000); 
}).then(function(result) { 
    $('#result').append(result+' @ '+(new Date().getSeconds())+'<br>'); 
}); 

的jsfiddle http://jsfiddle.net/4xxps2cg/2/

+0

您的回答是最乾淨的代碼:) –

+0

很高興幫助過,Max! –

+2

請修改參數'resolve,reject'。傳遞給'.then()'處理程序的是一個單獨的值,它不應該被命名爲'resolve'或'reject'。 – jfriend00

1

waitFor()似乎在.then()立即調用;請嘗試從.then()匿名函數返回waitFor()

可替代地創建持續時間值的數組,使用Array.prototype.shift()相繼調用waitFor與每個持續時間值,或通過參數timeoutwaitFor;如果在每個.then()處調用相同的過程,則包括在.then()處鏈接到Promise處的waitFor;調用同樣的功能waitFor.then()鏈接到初始waitFor()電話

var t = [1000, 2000, 3000]; 
function waitFor(timeout) { 
    return new Promise(function (resolve, reject) { 
     setTimeout(function() { 
      resolve("`Finished waiting ${timeout} milliseconds`"); 
     }, timeout && t.shift() || t.shift()); 
    }).then(function (data) { 
     $('#result').append(data + ' @ ' + new Date().getSeconds() + '<br/>'); 
    }) 
} 

waitFor().then(waitFor).then(waitFor) 
//.then(function() {return waitFor(5000)}) 
+0

爲什麼只有一個回報? –

+0

@MaxMastalerz初始'waitFor'返回最初的'Promise','.then()'在首次調用'waitFor(1000)'後只需要將promise返回給鏈中的最後一個'.then()' – guest271314

0

調用和等待的格式是有點過了,你then應該是返回一個承諾的功能,因爲現在你傳遞一個函數調用,而不是一個功能,它的立即運行該請求,而不是等待由於承諾而調用該函數。

這應做到:

function waitFor(timeout) { 
    return new Promise(function(resolve, reject) { 
     setTimeout(function() { 
      resolve(`Finished waiting ${timeout} milliseconds`); 
     }, timeout); 
    }); 
} 

waitFor(1000).then(function(resolve, reject) { 
    $('#result').append(resolve+' @ '+new Date().getSeconds()+'<br/>'); 
}).then(function(){ 
    return waitFor(2000) 
}).then(function(resolve, reject) { 
    $('#result').append(resolve+' @ '+new Date().getSeconds()+'<br/>'); 
}).then(function() { 
    return waitFor(2000) 
}).then(function(resolve, reject) { 
    $('#result').append(resolve+' @ '+new Date().getSeconds()+'<br/>'); 
}) 
2

你可以把承諾轉化爲數組,並使用reduce到鏈他們,從一個額外的解決前景。

function waitPromise(time) { 
    //console.log(time); 
    return new Promise((resolve,reject) => { 
    setTimeout(() => {resolve('resolved');}, time); 
    }); 
} 

function log(data) { 
    return new Promise((resolve,reject) => { 
    console.log(data +' @ '+(new Date().getSeconds())); 
    resolve(); 
    }); 
} 

var ps = []; 
for (var i=0;i<3;i++) { 
    let time = (i+1) * 1000; 
    ps.push(() => waitPromise(time)); 
    ps.push(log); 
} 


console.log('started' +' @ '+(new Date().getSeconds())); 
var p = Promise.resolve(); 
ps.reduce((p,c) => {return p.then(c)}, p);