owned this note
owned this note
Published
Linked with GitHub
# <font class="h2">Promise物件</font>
###### tags: `javascript`
<style>
.h2 {
background: linear-gradient(135deg,#fff,#537479) ;
color: #537479;
display:block;
padding: 6px 5px;
border-radius: 4px;
}
.h3 {
background: linear-gradient(180deg,#fff 50%,#c9d5d4) ;
color: #537479;
display:block;
padding: 6px 5px;
border-bottom: 3px solid #537479;
}
.h4 {
color: #537479;
font-weight:bold;
font-size:1.1em;
}
</style>
<br>
### <font class="h3">解決非同步的方法</font>
1. 回呼函示(早期)
2. Promise物件(es6)
3. Async/Await(es6)
<br>
:::info
語法:
```javascript
new Promise(執行程式){成功程序,失敗程序}
.then(()=>{成功時的動作})
.catch(()=>{失敗時的動作})
.finally(()=>{無論如何都會執行})
```
:::


<br>

<br><br><br><br>
```javascript
function mix(){
console.log(1)
setTimeout(()=>{console.log(2)},0)
console.log(3)
console.log(4)
}
mix() //1342
```
<br><br>
### callback解決非同步:
```javascript
function mix() {
console.log(1)
}
function second(callback) {
setTimeout(() => {
console.log(2)
callback()
}, 0)
}
function third() {
console.log(3)
console.log(4)
}
mix()
second(third)
```
<br><br>
### promise解決非同步:
```javascript
let def = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2)
}, 0);
})
function mix() {
console.log(1)
def.then((res) => {
console.log(res)
}).then(() => {
console.log(3)
console.log(4)
})
}
mix()
```
<br><br><br><br>
### <font class="h3">範例</font>
```javascript
function add(n1, n2){
return n1+n2;
}
function test(){
let result = add(3,4);
console.log(result);
}
test()//7
```
<br><br>
### 非同步範例:

return基本上失效了,印出結果是undefined
<br>
### <font class="h4">使用promise 範例1.</font>

<br>
可以這樣調整,比較常見是這樣寫,用return將Promise物件回傳

<br>
### resolve、reject參數

呼叫resolve會對應到then,如果呼叫reject會對應到catch
<br><br><br><br>
### <font class="h4">➤ promise 範例2.</font>
```javascript
function promiseFn(num,time = 500){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
if(num){
resolve(`成功${num}`)
}else{
reject('失敗')
}
},time)
})
}
promiseFn(1,2000)
.then(res =>{
console.log(res)
})
```
<br><br><br><br>
### <font class="h4">➤ promise 範例3.</font>

<br><br><br><br>
### <font class="h4">➤ 範例:resolve也可以回傳失敗</font>

<br><br><br><br>
### <font class="h4">➤多個promise任務範例:</font>
```javascript
function delayedAdd(n1, n2, delayTime){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
resolve(n1+n2);
},delayTime);
});
}
function test(){
let promise1 = delayedAdd(3,4,2000);
let promise2 = delayedAdd(2,3,3000);
//多個Promise 都完成之後,才繼續工作
Promise.all([promise1,promise2]).then(function(results){
console.log(results);//[7,5]
});
}
test()
```
`Promise.all`的`Promise`要大寫
<br><br><br><br>
### <font class="h4">➤多個promise任務做相乘範例:</font>
```javascript
function delayedAdd(n1, n2, delayTime){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
resolve(n1+n2);
},delayTime);
});
}
function test(){
let promise1 = delayedAdd(3,4,2000);
let promise2 = delayedAdd(2,3,3000);
//多個Promise 都完成之後,才繼續工作
Promise.all([promise1,promise2]).then(function(results){
let answer = results.reduce(function(total,value){
return total*value;
})
console.log(answer);//35
});
}
test()
```
<br><br><br><br>
### <font class="h3">Ajax方面</font>
### <font class="h4">➤Ajax使用Promise 範例:</font>
:bulb:這裡使用的是JavaScript原生寫法「XMLHttpRequest」
```javascript
function getData() {
let req = new XMLHttpRequest()
req.open("get", "https://training.pada-x.com/resources/javascript-es6-react/data.out")
req.onload = function () {
alert(this.responseText)
}
req.send()
}
getData();
```
### 使用then回傳連線失敗範例:

<br>
### 使用catch回傳連線失敗範例:
```javascript
function getData() {
return new Promise(function(resolve,reject){
let req = new XMLHttpRequest()
req.open("get", "https://training.pada-x.com/resources/javascript-es6-react/data.out")
req.onload = function(){
resolve(this.responseText)
};
req.onerror=function(){
reject("Error")
}
req.send()
})
}
let promise=getData();
promise.then(function(result){
alert(result)
}).catch(function(err){
alert(err)
})
```
<br><br><br><br>
### <font class="h4">➤Ajax使用Promise 範例2:</font>
```javascript
const url = 'https://randomuser.me/api'
Promise.all([axios.get(url),axios.get(url)])
.then(([res1,res2])=>{
console.log(res1,res2)
})
```

<br><br><br><br>
### <font class="h4">➤Ajax使用Promise 範例3:</font>
```javascript
const url = 'https://randomuser.me/api'
let data = {};
axios.get(url)
.then( res => {
data = res
})
console.log(data) //{}
```
這裡因為非同步的關係,data會是空物件
```javascript
const url = 'https://randomuser.me/api'
let data = {};
function getData(){
return new Promise((resolve,reject)=>{
axios.get(url)
.then( res => { resolve(res) })
})
}
getData().then(res=>{
data = res
console.log(data)
})
```
<br><br><br><br>
### <font class="h3">多個Promise執行順序方面 (鏈接技巧)Promise chain</font>
==鏈接可以避免巢狀結構==
### <font class="h4">➤範例1:</font>
```javascript
function promiseFn(num){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
if(num){
resolve(`成功${num}`)
}else{
reject('失敗')
}
},0)
})
}
promiseFn(1)
.then(res =>{
console.log(res)
return promiseFn(2)
})
.then(res =>{
console.log(res)
return promiseFn(3)
})
.then(res =>{
console.log(res)
})
.catch(res =>{
console.log('catch',res)
})
//成功1 成功2 成功3
```
<br><br><br>
### <font class="h4">➤範例2:</font>
```javascript
function funcA(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
console.log('A');
resolve('A');
},(Math.random()+1)*1000)
})
}
function funcB(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
console.log('B');
resolve('B');
},(Math.random()+1)*1000)
})
}
function funcC(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
console.log('C');
resolve('C');
},(Math.random()+1)*1000)
})
}
funcA().then(funcB).then(funcC)
```
這樣就可以做到等funcA()被「resolve」之後再執行funcB(),然後resolve再執行funcC()的順序了。
<br><br><br>
### <font class="h4">➤範例3: 使用return做promise額外請求串接</font>

<br><br><br>
### 使用Promise.all
如果不在乎funcA()、funcB()、funcC()誰先誰後的話,就就可以使用Promise.all
```javascript
function funcA(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
console.log('A');
resolve('A');
},(Math.random()+1)*1000)
})
}
function funcB(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
console.log('B');
resolve('B');
},(Math.random()+1)*1000)
})
}
function funcC(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
console.log('C');
resolve('C');
},(Math.random()+1)*1000)
})
}
Promise.all([funcA(),funcB(),funcC()]).then(()=>{console.log('上菜');});
```
要注意的是,在Promise.all()執行過程中只要有任一Promise物件執行發生錯誤或是Promise的reject情況,就會立即回傳一個reject狀態promise物件。
<br>
### Promise.race
只會回傳第一個
```javascript
function funcA(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
console.log('A');
resolve('A');
},(Math.random()+1)*1000)
})
}
function funcB(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
console.log('B');
resolve('B');
},(Math.random()+1)*1000)
})
}
function funcC(){
return new Promise(function(resolve,reject){
window.setTimeout(function(){
console.log('C');
resolve('C');
},(Math.random()+1)*1000)
})
}
Promise.race([funcA(),funcB(),funcC()]).then(()=>{console.log('上菜');});
```
相對於Promise.all()要等全部任務完成(resolve)才進行下一步,Promise.race()則是如同字面上含義的「競賽」一樣,只要有其中一個任務被resolve就會進行下一步。
<br><br><br>