那天我正在學習 Promise,忽然家裏打電話過來講,家裏蓋房子要錢。我工做這麼多年了,從事着別人眼中高薪工做,因而滿口答應下來。可是因爲我並無錢,因而我跟家裏說,等過幾天我再打錢過去。我也好乘着這幾天想一想辦法。數組
首先我找到個人同窗李雷,他如今一個部門經理了,我想應該他應該有錢。我跟他說明了借錢的意向,李雷二話不說就答應借我300,不過同時表示要回家跟老婆商量商量,我說好。此時我想起來答應或者說承諾的英文單詞就是 Promise
。承諾的結果是錢,錢是數值(number 類型)。因而我想把我要借錢的這一行爲寫成一個TypeScript
函數以下:promise
// 向李雷借錢,李雷丟給我一個承諾 function borrowMoneyFromLiLei(): Promise<number> { return new Promise<number>(function(fulfill, reject) { // 李雷跟老婆商量中 }); } 複製代碼
此時,我在想李雷老婆會答應給我借300塊嗎?我不肯定,就像薛定諤的貓。借仍是不借,這是一個問題。而後我發現這也能夠寫成一個函數。借或者不借用布爾值來表示 (boolean 類型)。函數以下:bash
// 李雷的老婆是否會答應給我借錢? function willLiLeiWifeLendMeMoeny(): Promise<boolean> { return new Promise<boolean>(function(lend, reject) { // 借仍是不借 }); } 複製代碼
若是李雷借我錢了,我就轉錢給家裏,沒有,我應該要再去找別人借了。能夠用下面的函數描述我此時的處境。markdown
function transferMoneyToHome(money: number) { // 給家裏轉錢 } function mySituation(){ borrowMoneyFromLiLei() .then((money:number) => { // 若是李雷借我錢了,我就轉錢給家裏. transferMoneyToHome(money) }).catch((reason) => { // 李雷老婆拒絕借錢給我。 那我應該考慮向其餘人借了。 borrowMoneyFromOthers() }) } 複製代碼
找其餘人借,我能想到就(張三,李四,五五)這三我的了,其餘的朋友不多聯繫,忽然說借錢也很差。因而我嘗試向他們借錢。用代碼表示是這樣子的:函數
function borrowMoneyFromOthers() { // 我先試着向張三借 tryBorrowMoneyFromZhangshan() .then(money => { transferMoneyToHome(money); }) .catch(reason => { // 若是張三不借,並丟給我一個理由 // 試着向李四借 tryBorrowMoneyFromLisi() .then(money => { transferMoneyToHome(money); }) .catch(reason2 => { // 若是 李四也不願錯 // 再試試向王五借 tryBorrowMoneyFromWangwu() .then(money => { transferMoneyToHome(money); }) .catch(reason => { // 沒有人肯借 throw new Error("我該怎麼辦呢?"); }); }); }); } 複製代碼
因爲藉着錢以後都是向家裏轉錢,因此上面的代碼應該簡化一下。簡化後以下:學習
function borrowMoneyFromOthers() { // 我先試着向張三借 tryBorrowMoneyFromZhangshan() .then(transferMoneyToHome) .catch(reason => { // 若是張三不借,並丟給我一個理由 // 試着向李四借 tryBorrowMoneyFromLisi() .then(transferMoneyToHome) .catch(reason2 => { // 若是 李四也不願錯 // 再試試向王五借 tryBorrowMoneyFromWangwu() .then(transferMoneyToHome) .catch(reason => { // 沒有人肯借 throw new Error("我該怎麼辦呢?"); }); }); }); } 複製代碼
在上面的思路中,我是一個一個找他們借錢的,一個借不着再找另外一個。我爲何不一樣時找他們借呢?誰借我了,我就轉錢給家裏。此時我想起了剛學的Promise.race
方法,也許這個方法能夠幫助我表達個人這一決策需求.spa
function borrowMoneyFromOthers() { // 同時向張三,李四,王五借錢,只要有人借我錢了,我就轉錢給家裏。 Promise.race([ tryBorrowMoneyFromZhangshan(), tryBorrowMoneyFromLisi(), tryBorrowMoneyFromWangwu() ]) .then(transferMoneyToHome) .catch(reasons => { console.warn("沒一我的願意給我借錢,他們理由是:", reasons); }); } 複製代碼
我用timeout 模擬一下他們給我答覆的,代碼以下:code
// 嘗試找張三借 function tryBorrowMoneyFromZhangshan(): Promise<number> { return new Promise(function(fulfill, reject) { setTimeout(() => { fulfill(300); }, 100); }); } // 嘗試找李四借 function tryBorrowMoneyFromLisi(): Promise<number> { return new Promise(function(fulfill, reject) { setTimeout(() => { reject("對不起我也沒錢"); }, 50); }); } // 嘗試找王五借 function tryBorrowMoneyFromWangwu(): Promise<number> { return new Promise(function(fulfill, reject) { setTimeout(() => { fulfill(300); }, 500); }); } 複製代碼
結果運行以後,控制檯輸出的是:orm
沒一我的願意給我借錢,他們理由是: 對不起我也沒錢ip
看來 Promise.race
適用用來模擬搶答,而不是選擇最優解。 好比多人搶答一個問題,第一個搶答以後不論他回答的是不是正確,這個題都過了。
不過不要緊。也許我能夠本身寫一個來叫作 promiseOne
的函數來實現這個功能。代碼以下:
/** * 當其中一個 Promise 兌現時,返回的 Promise 即被兌現 * @param promises Promise<T> 的數組 */ function promiseOne<T>(promises: Promise<T>[]): Promise<T> { const promiseCount = promises.length; return new Promise<T>(function(resolve, reject) { const reasons: any[] = []; let rejectedCount = 0; promises.forEach((promise, index) => { promise.then(resolve).catch(reason => { reasons[index] = reason; rejectedCount++; if (rejectedCount === promiseCount) { reject(reasons); } }); }); }); } 複製代碼
正當我寫完了上面的代碼,他們三個給我回話了,說是如今手上也沒有那麼多錢,可是能夠給我借100. 因而我如今須要處理這樣的事情,就是當他們三我的把錢都轉給我以後我再轉給家裏。 當他們三個都兌換借我100塊錢的承諾時,能夠用 Promise.all
來表示,代碼以下:
function borrowMoneyFromOthers() { // 同時向張三,李四,王五借錢, 借到以後,我就轉錢給家裏。 Promise.all([ tryBorrowMoneyFromZhangshan(), tryBorrowMoneyFromLisi(), tryBorrowMoneyFromWangwu() ]) .then(moneyArray => { console.info("借到錢啦:", moneyArray); const totalMoney = moneyArray.reduce((acc, cur) => acc + cur); transferMoneyToHome(totalMoney); }) .catch(reasons => { console.warn("有人不肯意給我借錢,理由是:", reasons); }); } 複製代碼
如今有三我的願意給我借錢了,嗯,也就是說我借到了 300 塊。然而這錢用來建房仍是杯水車薪。因此我還得想辦法。我想我要不要試試用這300塊來買一下彩票。若是中了,說不定這事就成了。
function buyLottery(bet: number): Promise<number> { return new Promise(function(fulfill, resolve) { // 投注 // 等待開獎 setTimeout(() => { resolve("很遺憾你沒有買中"); }, 100); }); } function borrowMoneyFromOthers() { // 同時向張三,李四,王五借錢, Promise.all([ tryBorrowMoneyFromZhangshan(), tryBorrowMoneyFromLisi(), tryBorrowMoneyFromWangwu() ]) .then(moneyArray => { console.info("借到錢啦:", moneyArray); const totalMoney = moneyArray.reduce((acc, cur) => acc + cur); // 購買彩票 buyLottery(totalMoney) .then(transferMoneyToHome) .catch(reason => { console.log("沒中,", reason); }); }) .catch(reasons => { console.warn("有人不肯意給我借錢,理由是:", reasons); }); } 複製代碼
我知道很大機率我是買不中的,最近世界盃開賽了,我幻想着壓注世界盃,並且世界盃場次多,一天好幾場,一場買中的盈利還能夠投入到下一場。我把個人幻想寫成代碼,大概就是下面這樣。
function betWorldCup() { // 初始資金 300 塊 Promise.resolve(300) .then(moeny => { // 投西班牙 return new Promise<number>(function(fulfil, reject) { setTimeout(() => { // 假假設 賠率 1.2 fulfil(moeny * 1.2); }, 100); }); }) .then(ret => { // 投英格蘭 return ret * 1.2; }) .then(ret => { // 投巴西 return new Promise<number>(function(fulfil, reject) { setTimeout(() => { fulfil(ret * 1.2); }, 92); }); }) .then(ret => { console.log("如今收益加本金共有: ", ret); }); } 複製代碼
我想,若是第一場投失敗了,應該再給本身一次機會。因而將代碼修改以下:
function betWorldCup() { // 初始資金 300 塊 Promise.resolve(300) .then(moeny => { // 投西班牙 return new Promise<number>(function(fulfil, reject) { setTimeout(() => { // 假假設 賠率 1.2 // fulfil(moeny * 1.2); reject("莊家跑跑路了"); }, 100); }); }) .then( ret => { // 投英格蘭 return ret * 1.2; }, reason => { console.info("第一次投注失敗,再給一次機會好很差?, 失敗緣由: ", reason); // 再投 300 return 300; } ) .then(ret => { // 投巴西 return new Promise<number>(function(fulfil, reject) { setTimeout(() => { fulfil(ret * 1.2); }, 92); }); }) .then(ret => { console.log("如今收益加本金共有: ", ret); throw new Error("不要再買了"); }) .then(ret => { console.info("準備再買嗎?"); }) .catch(reason => { console.log("出錯了:", reason); }); } 複製代碼
此時以下運行上面的函數會獲得以下輸出:
第一次投注失敗,再給一次機會好很差?, 失敗緣由: 莊家跑跑路了
如今收益加本金共有: 360
出錯了:
Error: 不要再買了
複製代碼
然而,幻想結束以後,我依然得苦苦思考怎麼樣籌錢。