2017-02-24 51 views
1

我無法正確使用JS中的承諾,看起來像什麼。如何有效地使用JS Promisses?

我有3個異步相互依賴的功能,像這樣:

的func1,func2函數和FUNC 3.

  • func1的返回FUNC2用途的單個結果。
  • func2還返回單個結果
  • func3使用func1和func2的結果。

所以func3必須等待func1和2,而func2只能等待func1。

這裏是JS小提琴,我可以編寫,它的工作原理,但閱讀3一起使用的混亂只是一個nighmare。什麼是執行這種連鎖經營的正確方法?

function func1() { 
 
    return new Promise(function(resolve, reject) { 
 
    setTimeout(function() { 
 
     resolve(10); 
 
    }, 1000); 
 
    }); 
 
} 
 

 
function func2(return1) { 
 
    return new Promise(function(resolve, reject) { 
 
    setTimeout(function() { 
 
     resolve(return1 + 20); 
 
    }, 1000); 
 
    }); 
 
} 
 

 
function func3(val1, val2) { 
 
    return new Promise(function(resolve, reject) { 
 
    setTimeout(function() { 
 
     resolve(val1 + val2); 
 
    }, 1000); 
 
    }); 
 
} 
 

 
func1().then(function(result) { 
 
    func2(result).then(function(result2) { 
 
    func3(result, result2).then(function(finalResult) { 
 
     console.log(finalResult); 
 
    }, function(err) { 
 
     console.log(err); 
 
    }); 
 
    }); 
 
}).catch(function(err) { 
 
    console.log(err); 
 
});

+2

我投票結束這個問題作爲題外話,因爲如何改進/重新設計工作代碼的建議請求屬於CodeReview。stackexchange.com。 – Barmar

+0

我不確定還有很大的改進空間。我沒有看到多餘的代碼,它直接表達了設計要求。你是否需要對N個函數進行概括,每個函數都需要得到所有前面函數的結果? – Barmar

+0

您可能也對此感興趣[如何鏈接並與承諾共享先前的結果](http://stackoverflow.com/questions/28714298/how-to-chain-and-share-prior-results-with-promises/28714863 #28714863)。這涵蓋了在鏈接承諾時訪問多個先前結果的各種選項。 – jfriend00

回答

5

只使用承諾,您可以使用封閉範圍和巢您的承諾(這是你在做什麼),或者你可以傳遞多個結果像這樣的對象:

func1() 
    .then((result) => { 
    return func2(result).then((result2) => ({result, result2})); 
    }) 
    .then(({result, result2}) => { 
    return func3(result, result2); 
    }); 

或者你可以存儲之外的所有承諾的範圍結果:

let result; 

func1() 
    .then((_result) => { 
    result = _result; 
    return func2(result); 
    }) 
    .then((result2) => { 
    return func3(result, result2); 
    }); 

如果環境支持async/await functions,你可以把它改寫這樣的:

async function fn() { 
    const result = await func1(); 
    const result2 = await func2(result); 
    const result3 = await func3(result, result2); 

    return result3; 
} 

fn().then((result3) => console.log(result3)); 

如果您的環境支持發電機,您可以使用co庫創建協程:

const fn = co.wrap(function*() { 
    const result = yield func1(); 
    const result2 = yield func2(result); 
    const result3 = yield func3(result, result2); 

    return result3; 
}); 

fn().then((result3) => console.log(result3)); 
+0

我喜歡異步等待,這是更清潔。然而,將結果作爲對象符號傳遞給我似乎是一個糟糕的設計,因爲這會表明func2只會被func3使用,因爲它實際上將func1的值傳遞給了進一步鏈接的func,但它不應該這樣。 – Alexus

0

編輯:我誤讀了要求。 SimpleJ在這裏的答案是要走的路。

then回調中返回的值本身是可用的。換句話說,您可以通過返回前一個then回調中的下一個函數來按順序處理您的承諾。

而不是

func1().then(function(result) { 
 
    func2(result).then(function(result2) { 
 
    func3(result, result2).then(function(finalResult) { 
 
     console.log(finalResult); 
 
    }, function(err) { 
 
     console.log(err); 
 
    }); 
 
    }); 
 
}).catch(function(err) { 
 
    console.log(err); 
 
});

試試這個:

func1() 
 
    .then(result => func2(result)) 
 
    .then(result => func3(result)) 
 
    .then(result => console.log('Final result', result)) 
 
    .catch(err => console.error(err))

我轉換了您的功能箭頭功能收拾了一下更多,但功能上它和你的一樣。

+1

但是func3需要func1和func2的結果,在你的解決方案中它只接受func2的結果。不是嗎? – Alexus

+0

啊,是的,我錯過了。我會調整答案。 –