欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript中Promise的使用方法實例

 更新時間:2022年05月12日 11:01:56   作者:An595  
現(xiàn)在不會用Promise都不好意思說自己是前端,下面這篇文章主要給大家介紹了關(guān)于JavaScript中Promise使用的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

我還記得我剛開始學(xué)習(xí)JavaScript的Promise很多概念都不懂很"懵逼", 現(xiàn)在已經(jīng)工作有小半年時間了, 整理整理筆記和個人在工作中的使用情況, 寫個文章記錄一下(PS只記錄怎么使用, 原理太深奧功力不夠), 如果有不對的地方前輩勿噴??

Promise簡介

Promise也稱期約, 是ES6推出的一個異步解決方案, 可以有效的解決異步函數(shù)嵌套太深("回調(diào)地獄")的問題

什么是回調(diào)地獄?

假設(shè)有個需求需要獲取用戶的指定數(shù)據(jù)用戶數(shù)據(jù)3這個數(shù)據(jù)依賴用戶數(shù)據(jù)2用戶數(shù)據(jù)2又依賴于用戶數(shù)據(jù)1, 所以正確的數(shù)據(jù)獲取數(shù)據(jù)順序為: 用戶數(shù)據(jù)1-->用戶數(shù)據(jù)2-->用戶數(shù)據(jù)3, 模擬一下使用回調(diào)函數(shù)的寫法如下:

Node接口:

const router = require('express').Router();

const data1 = { data: "用戶數(shù)據(jù)1" };
router.get('/testData1', (req, res) => {
    res.json(data1);
})

const data2 = { data: "用戶數(shù)據(jù)1,用戶數(shù)據(jù)2" };
router.get('/testData2', (req, res) => {
    if (req.query.data === data1.data) {
        res.json(data2);
    } else {
        res.status(401).json("參數(shù)錯誤");
    }
})

router.get('/testData3', (req, res) => {
    if (req.query.data === data2.data) {
        res.json({ data: "用戶數(shù)據(jù)1,用戶數(shù)據(jù)2,用戶數(shù)據(jù)3" });
    } else {
        res.status(401).json("參數(shù)錯誤");
    }
})

module.exports = router;

前端請求代碼:

// 簡單封裝的 XMLHttpRequest 請求函數(shù)
const baseUrl = "http://localhost:8888/test";
const request = (url, cb) => {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', baseUrl + url);
  xhr.send();
  xhr.onreadystatechange = () => {
    const { readyState, status, response } = xhr;
    if (readyState === 4) {
      if (status >= 200 && status <= 299) {
        cb(JSON.parse(response));
      } else {
        throw new Error(response);
      }
    }
  }
}

// 因為下一個請求需要上一個請求的數(shù)據(jù)所以需要一個回調(diào)函數(shù)嵌套一個回調(diào)函數(shù)
request("/testData1", res1 => {
  console.log(res1); // => {data: '用戶數(shù)據(jù)1'}
  request(`/testData2?data=${res1.data}`, res2 => {
    console.log(res2); // => {data: '用戶數(shù)據(jù)1,用戶數(shù)據(jù)2'}
    request(`/testData3?data=${res2.data}`, res3 => {
      console.log("需求需要的數(shù)據(jù)", res3); // => 需求需要的數(shù)據(jù) {data: '用戶數(shù)據(jù)1,用戶數(shù)據(jù)2,用戶數(shù)據(jù)3'}
      // ....
    })
  })
})

這個代碼看著就頭大, 如果需求復(fù)雜的話, 我只能用一張圖表示(這張圖片我也不記得從哪里保存的忘了??)

這種一個回調(diào)嵌套一個回調(diào)的代碼可讀性和可維護(hù)性都很差, 被稱為"回調(diào)地獄", 而Promise的出現(xiàn)就可以很好的解決這個問題

Promise的特點(diǎn)

Promise對象有一個狀態(tài), 這個狀態(tài)不受外界影響, 狀態(tài)一共分為3種:

  • Pending狀態(tài) (進(jìn)行中(又稱待定)) 初始狀態(tài)
  • Fulfilled狀態(tài) (成功(又稱兌現(xiàn)))
  • Rejected狀態(tài)(失敗(又稱拒絕))

關(guān)于Promise的狀態(tài)叫法下文統(tǒng)一使用成功,失敗

一旦Promise對象的狀態(tài)改變(成功或失敗)就不會再變, 是單向的:

Pending(進(jìn)行中) -> Fulfilled(成功)

Pending(進(jìn)行中) -> Rejected(失敗)

創(chuàng)建Promise實例

創(chuàng)建Promise實例需要newPromise構(gòu)造函數(shù), 該構(gòu)造函數(shù)接受一個函數(shù)(處理器函數(shù))作為參數(shù), 該函數(shù)會收到兩個參數(shù), 這兩個參數(shù)分別是resolve和reject(叫什么都行一般還是要語義化名稱)它們是兩個函數(shù), 不用自己實現(xiàn)就可以使用, 如下:

const p = new Promise((resolve, reject) => {

})
console.log(p);

可以看到這個狀態(tài)默認(rèn)是Pending(進(jìn)行中)

resolve和reject這兩個參數(shù)(函數(shù))可以在處理器函數(shù)里面調(diào)用(可以傳遞參數(shù)), 這樣將會改變 Promise 對象的狀態(tài):

const p = new Promise((resolve, reject) => {
  resolve();
})
console.log(p);

當(dāng)調(diào)用resolve函數(shù)時會將Priomise對象的狀態(tài)修改為Fulfilled(成功), 調(diào)用reject函數(shù)則會將狀態(tài)修改為Rejected(失敗)

then方法

Promise實例的then方法, 可以接受兩個參數(shù)(都是函數(shù))分別指定Primise實例里面狀態(tài)(成功或失敗)改變時調(diào)用的回調(diào)函數(shù)(并且Promise的then方法是異步的微任務(wù)):

const p = new Promise((resolve, reject) => {
  // 將p的狀態(tài)修改為成功 
  resolve();
})
    
console.log("同步代碼");
p.then(
  () => {
    console.log("成功的回調(diào)");
  },
  () => {
    console.log("失敗的回調(diào)");
  }
)

結(jié)果如下:

反之調(diào)用reject函數(shù)就會觸發(fā)then方法的第二個回調(diào)函數(shù), 如果將resolve函數(shù)和reject函數(shù)都調(diào)用只會生效最先調(diào)用的(因為狀態(tài)時單向的嘛)

resolve 和 reject 的參數(shù)傳遞

經(jīng)過上面的測試我們知道resolve和reject這兩個函數(shù)是可以修改狀態(tài)并且觸發(fā)Promise的then方法的回調(diào)函數(shù)的, 那么是函數(shù)就可以傳遞參數(shù), 這個參數(shù)會被傳遞給對應(yīng)的then方法的回調(diào)函數(shù)接收到:

const p = new Promise((resolve, reject) => {
  // 將p的狀態(tài)修改為成功, 并且傳遞一個參數(shù)
  resolve("ok");
})

console.log("同步代碼");
p.then(
  // 這里接收 resolve 函數(shù)傳遞的參數(shù)
  res => {
    console.log("成功的回調(diào)", res);
  },
  // 這里接收 reject 函數(shù)傳遞的參數(shù)
  err => {
    console.log("失敗的回調(diào)");
  }
)

結(jié)果如下:

then()鏈?zhǔn)秸{(diào)用

了解完then方法以后我們就可以稍微修改一下一開始最上面的需求:

// 請求函數(shù)使用 Promise 封裝
const baseUrl = "http://localhost:8888/test";
const request = (url) => {
  // 返回一個Promise實例
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', baseUrl + url);
    xhr.send();
    xhr.onreadystatechange = () => {
      const { readyState, status, response } = xhr;
      if (readyState === 4) {
        if (status >= 200 && status <= 299) {
          const res = JSON.parse(response);
          // 修改狀態(tài)為成功并且把響應(yīng)傳遞過去
          resolve(res);
        } else {
          // 修改狀態(tài)為失敗也把響應(yīng)傳遞過去
          reject(response);
        }
      }
    }
  })
}

// 使用then方法
request("/testData1").then(
  res1 => {
    console.log(res1); // {data: '用戶數(shù)據(jù)1'}
    request(`/testData2?data=${res1.data}`).then(
      res2 => {
        console.log(res2); // {data: '用戶數(shù)據(jù)1,用戶數(shù)據(jù)2'}
        request(`/testData3?data=${res2.data}`).then(
          res3 => {
            console.log("需求需要的數(shù)據(jù)", res3); // => 需求需要的數(shù)據(jù) {data: '用戶數(shù)據(jù)1,用戶數(shù)據(jù)2,用戶數(shù)據(jù)3'}
          }
        )
      }
    )
  }
)

寫完以后發(fā)現(xiàn)好像還不如使用回調(diào)函數(shù)的方式寫, 看到這里好像Promise還是不能很好的解決回調(diào)嵌套的問題; 換個思路如果我們在then方法中再返回一個Promise實例, 那么不就又可以調(diào)用then方法了嗎? 代碼中測試一下:

const p1 = new Promise((resolve, reject) => {
  resolve("p1數(shù)據(jù)");
})

// 這里的p2就是p1.then方法成功回調(diào)里面返回的p2
const p2 = p1.then(
    // 這里的res1參數(shù)就是p1的處理器函數(shù)中調(diào)用 resolve("p1數(shù)據(jù)") 傳遞的參數(shù)
    res1 => {
      console.log(res1); // p1數(shù)據(jù)

      // 這里新建一個新的Promise實例, 記作p2
      const p2 = new Promise((resolve, reject) => {
        // 0.5s后修改狀態(tài)
        setTimeout(() => {
          resolve(res1 + ",p2數(shù)據(jù)");
        }, 500);

      })
      // 將p2返回
      return p2;
    }
  )

const p3 = p2.then(
  res2 => {
    console.log(res2); // p1數(shù)據(jù),p2數(shù)據(jù)
    // 這里和上面的同理
    const p3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(res2 + ",p3數(shù)據(jù)");
      }, 500);

    })
    return p3;
  }
)

p3.then(
  res3 => {
    console.log(res3); // p1數(shù)據(jù),p2數(shù)據(jù),p3數(shù)據(jù)
  }
)

發(fā)現(xiàn)可行后, 把需求代碼再修改一下:

// 這里的p1就是 request("/testData1") 返回的Promise實例
const p1 = request("/testData1");

// 這里的p2就是p1.then方法成功回調(diào)返回的p2
const p2 = p1.then(
    res1 => {
      console.log(res1); // {data: '用戶數(shù)據(jù)1'}

      // 再調(diào)用request方法將其返回的Promise實例記作p2
      const p2 = request(`/testData2?data=${res1.data}`);
      // 將p2返回
      return p2;
    }
  )

const p3 = p2.then(
  res2 => {
    console.log(res2); // {data: '用戶數(shù)據(jù)1,用戶數(shù)據(jù)2'}
    // 這里和上面的同理
    const p3 = request(`/testData3?data=${res2.data}`);
    return p3;
  }
)

p3.then(
  res3 => {
    console.log("需求需要的數(shù)據(jù)", res3); // 需求需要的數(shù)據(jù) {data: '用戶數(shù)據(jù)1,用戶數(shù)據(jù)2,用戶數(shù)據(jù)3'}
  }
)

需求實現(xiàn)是實現(xiàn)了, 就是代碼有點(diǎn)冗余, 可以精簡一下, 如下:

request("/testData1").then(
  res1 => {
    console.log(res1); // {data: '用戶數(shù)據(jù)1'}
    // 這里直接返回 request方法的返回值Promise實例
    return request(`/testData2?data=${res1.data}`);
  }
).then( 
  // 這個成功回調(diào)時上一個then方法返回的Promise實例的成功回調(diào)
  res2 => {
    console.log(res2); // {data: '用戶數(shù)據(jù)1,用戶數(shù)據(jù)2'}
    // 同理
    return request(`/testData3?data=${res2.data}`);
  }
).then(
  // 同理
  res3 => {
    console.log("需求需要的數(shù)據(jù)", res3); // 需求需要的數(shù)據(jù) {data: '用戶數(shù)據(jù)1,用戶數(shù)據(jù)2,用戶數(shù)據(jù)3'}
  }
)

上面的代碼格式就像鏈條一樣所以又被稱為"鏈?zhǔn)秸{(diào)用"

then()的返回值

經(jīng)過上面的代碼測試, then方法除了返回Promise對象外還可以返回其他任意的值, 返回會被轉(zhuǎn)換為Promise對象, 內(nèi)部的狀態(tài)視返回值而定:

const p1 = new Promise(resolve => resolve());
p1.then(() => {
  // 這里相當(dāng)于是 return undefined
}).then(
  res1 => {
    console.log(res1); // undefined
    return "hello";
  }
).then(
  res2 => {
    console.log(res2); // hello
    return { name: "張三" };
  }
).then(
  res3 => {
    console.log(res3); // { name: "張三" }

    // 返回錯誤對象該P(yáng)romise對象的狀態(tài)也是成功
    return new Error("error object");
  }
).then(
  res4 => {
    console.log(res4 instanceof Error); // true
    console.log(res4.message); // error object

    // 拋出一個錯誤則該P(yáng)romise對象的狀態(tài)是失敗
    throw "thorw error";
  }
).then(
  () => { },
  err => {
    console.log(err); // thorw error
  }
)

catch方法

上面使用then方法的鏈?zhǔn)秸{(diào)用可以解決回調(diào)嵌套太深的問題, 但是還沒處理請求之間的失敗回調(diào)處理, then方法的第二個回調(diào)就是指定失敗的回調(diào), 但是一般都不使用這個回調(diào)來處理錯誤, 而是使用catch方法來失敗, 使用格式如下:

p1.then(
  // ...
).then(
  // ...

).catch(err => { // 這個catch可以捕獲這一條調(diào)用鏈上的錯誤
    // 處理錯誤
})

finally方法

除了catch方法那自然就有finally方法, finally方法和try...catch...finally中的finally是一樣的作用, 使用格式如下:

p.then(
  // ...
).then(
  // ...

).catch(err => { // 這個catch方法可以捕獲這一條調(diào)用鏈上的錯誤
  // 處理錯誤
    
}).finally(() => { // 無論成功還是失敗這個finally中指定的回調(diào)都會執(zhí)行
  // 清除loading, 重置狀態(tài)...
})

Promise的方法

Promise.resolve()

立即返回一個狀態(tài)是成功(Fulfilled) 的 Promise 對象, 可以傳遞參數(shù), 參數(shù)會被其返回的Promise實例的then方法的回調(diào)(異步微任務(wù))接受到:

const p = Promise.resolve("Promise.resolve");
p.then(res => console.log(res)); // Promise.resolve

也可以利用Promise.resolve()來創(chuàng)建一個微任務(wù):

console.log("同步代碼");

setTimeout(() => console.log("setTimeout"), 0);

const p = Promise.resolve("Promise.resolve");
p.then(res => console.log(res));

結(jié)果如下:

Promise.reject()

Promise.resolve()一樣不過返回的狀態(tài)是失敗(Rejected) 的Promise對象(同樣是微任務(wù))

console.log("同步代碼");

setTimeout(() => console.log("setTimeout"), 0);

const p = Promise.reject("Promise.reject");
p.then().catch(err => console.log("Promise.reject"));

Promise.all()

Promise.all接收一個Promise的iterable類型(就是可迭代對象里面存放著Promise實例, Array, Map, Set都屬于ES6的iterable類型), Promise.all 會等待所有的Promise對象都完成(或第一個失敗) , 根據(jù)給定的參數(shù)返回不同的參數(shù)

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p1 data"), 500);
})
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p2 data"), 1000);
})
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p3 data"), 1500);
})

// 依次打印數(shù)據(jù)
p1.then(res => console.log(res)); // 0.5s 后打印 p1 data
p2.then(res => console.log(res)); // 1.0s 后打印 p2 data
p3.then(res => console.log(res)); // 1.5s 后打印 p3 data


const proArray = [p1, p2, p3];
Promise.all(proArray).then(resList => {
  console.log(resList); // 1.5s后打印數(shù)據(jù) ['p1 data', 'p2 data', 'p3 data']
}).catch(err => {
  // 如果在`Promise.all`方法中出現(xiàn)了失敗的狀態(tài), 那么這個參數(shù)會是這個失敗狀態(tài)返回的參數(shù)(如果有的話)
  console.error("error: ", err); 
})

利用Promise.all()方法的特定可以用于同時發(fā)送多個請求, 如下例子:

Node接口:

const getRandom = () => Math.random() * 9 + 1;
router.get('/testData4', (req, res) => {
    let n = req.query.n;
    const random = getRandom();

    // 定時器模擬接口響應(yīng)時間差
    setTimeout(() => {
        res.json(`第${++n}個請求${random}`);
    }, random * 50);
});

前端發(fā)送多個請求:

const proArray = [];
for (let i = 0; i < 10; i++) {
  // 將10個請求方法返回的Promsie對象添加到proArray數(shù)組中
  proArray.push(request(`/testData4?n=${i}`));
}
Promise.all(proArray).then(resList => {
  for (const res of resList) {
    // 每個請求的返回結(jié)果
    console.log(res);
  }
})

Promise.allSettled()

Promise.allSettled()方法和Promise.all()很類似只不過是接受的期約對象無論是成功還是失敗都會觸發(fā)then方法的成功回調(diào), 每個期約都會返回一個對象status屬性表示狀態(tài), value表示成功回調(diào)的值, 如果狀態(tài)是失敗的那么失敗回調(diào)的值存儲在reason屬性中:

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p1 data"), 500);;
})
const p2 = new Promise((resolve, reject) => {
  // p2的Promise實例的狀態(tài)修改為失敗
  setTimeout(() => reject("p2 err"), 1000);
})

const proArray = [p1, p2];
Promise.allSettled(proArray).then(resList => {
  console.log(resList); // (2) [{…}, {…}]

  for (const res of resList) {
    const { status, value, reason } = res;
    if (reason) {
      console.log(`失敗: ${status}, 原因是: ${reason}`); // 失敗: rejected, 原因是: p2 err
    } else { 
      console.log(`成功: ${status}, 數(shù)據(jù)是: ${value}`); // 成功: fulfilled, 數(shù)據(jù)是: p1 data
    }
  }
}).catch(err => {
  // 這里不會捕獲p2的失敗的回調(diào) 
  console.error("error: ", err);
})

Promise.race()

Promise.race()Promise.all()類似, 都接收一個可以迭代的參數(shù), 但是不同之處是

Promise.race()的狀態(tài)變化不是受全部參數(shù)的狀態(tài)影響, 一旦迭代器中的某個Promise解決或拒絕,返回的 Promise就會解決或拒絕

const p1 = new Promise((resolve, reject) => {
    setTimeout(() => resolve("p1 data"), 500);;
})
const p2 = new Promise((resolve, reject) => {
    setTimeout(() => reject("p2 err"), 1000);
})

const proArray = [p1, p2];
Promise.race(proArray).then(res => {
    console.log(res); // p1 data
}).catch(err => {
    console.error(err);
})

async 和 await

async函數(shù)函數(shù)

async函數(shù)函數(shù)就是使用async關(guān)鍵字聲明的函數(shù)(也叫異步函數(shù)), async函數(shù)和普通的函數(shù)使用沒有什么區(qū)別:

// 函數(shù)聲明
async function asyncFn1() {
  console.log("asyncFn1");
}

// 函數(shù)表達(dá)式
const asyncFn2 = async () => {
  console.log("asyncFn2");
}

asyncFn1();
asyncFn2();

// 立即調(diào)用
(async () => {
  console.log("asyncFn3");
})();

await

await操作符用于等待一個Promise對象, 它只能在async function中使用, 使用async+await可以將異步的代碼"變"的跟同步的一樣:

const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("data");
  }, 1000);
});

// async 函數(shù)
async function asyncFn() {
  console.log("asyncFn函數(shù)開始執(zhí)行");

  // await 會等待右邊的Promise對象的狀態(tài)變成功后返回其值
  const res = await p;
  console.log(res); // data

  console.log("asyncFn函數(shù)執(zhí)行完了");
}

// 調(diào)用
asyncFn();

上面的代碼會先輸出"asyncFn函數(shù)開始執(zhí)行"后, 等待1s左右輸出"data", 然后再輸出"asyncFn函數(shù)執(zhí)行完了"

注意: 異步函數(shù)不會阻塞主線程的執(zhí)行, 它是異步的:

const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("data");
  }, 1000);
});

// async 函數(shù)
async function asyncFn() {
  console.log("asyncFn函數(shù)開始執(zhí)行");
  const res = await p;
  console.log(res); 
  console.log("asyncFn函數(shù)執(zhí)行完了");
}

console.log("hello");
asyncFn(); 
console.log("javascript");

等待大約1s后上面的代碼執(zhí)行結(jié)果如下:

根據(jù)上面的代碼執(zhí)行結(jié)果, 我們發(fā)現(xiàn)異步函數(shù)內(nèi)await關(guān)鍵字會等待其右邊的Promise對象的返回值, 等待結(jié)束后, 后面的代碼才會被執(zhí)行, 利用這個特性我們可以在JavaScript中可以實現(xiàn)類似Java的Thread.sleep()方法, 如下:

const sleep = async time => new Promise(resolve => setTimeout(resolve, time));

(async () => {
  console.log("1");
  await sleep(1000);
  console.log("2");
  await sleep(500);
  console.log("2.5");
})();

了解完async和await的使用后我們可以使用異步函數(shù)再來完成我們一開始的需求:

// 請求函數(shù)使用 Promise 封裝
const baseUrl = "http://localhost:8888/test";
const request = (url) => {
  // 返回一個Promise實例
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', baseUrl + url);
    xhr.send();
    xhr.onreadystatechange = () => {
      const { readyState, status, response } = xhr;
      if (readyState === 4) {
        if (status >= 200 && status <= 299) {
          const res = JSON.parse(response);
          // 修改狀態(tài)為成功并且把響應(yīng)傳遞過去
          resolve(res);
        } else {
          // 修改狀態(tài)為失敗也把響應(yīng)傳遞過去
          reject(response);
        }
      }
    }
  })
}

async function asyncFn() {
  const res1 = await request("/testData1");
  console.log(res1); // {data: '用戶數(shù)據(jù)1'}

  const res2 = await request(`/testData2?data=${res1.data}`);
  console.log(res2); // {data: '用戶數(shù)據(jù)1,用戶數(shù)據(jù)2'}

  const res3 = await request(`/testData3?data=${res2.data}`);
  console.log(res3); // {data: '用戶數(shù)據(jù)1,用戶數(shù)據(jù)2,用戶數(shù)據(jù)3'}
}

asyncFn();

可以看到使用async和await來發(fā)送網(wǎng)絡(luò)請求寫的代碼很簡潔, 也很直觀

異步函數(shù)的錯誤處理

異步函數(shù)的異常處理可以使用try...catch和catch處理:

try...catch

async function asyncFn() {
  let res1, res2, res3;
  try {
    res1 = await request("/testData1");

    try {
      if (res1?.data) {
        res2 = await request(`/testData2?data=${res1.data}`);
      }

      try {
        if (res2?.data) {
          res3 = await request(`/testData3?data=${res2.data}`);
        }

      } catch (error) {
        // 處理res3 error
      }

    } catch (error) {
      // 處理res2 error
    }

  } catch (error) {
    // 處理res3 error
  }
}

catch

async function asyncFn() {
  const res1 = await request("/testData1")
    .catch(err => {
      // 處理res1 error
    });

  if (res1?.data) {
    const res2 = await request(`/testData2?data=${res1.data}`)
      .catch(err => {
        // 處理res2 error
      });

    if (res2?.data) {
      const res3 = await request(`/testData3?data=${res2.data}`)
        .catch(err => {
          // 處理res3 error
        });
    }
  }
}

異步函數(shù)同樣適用于Promise的一些靜態(tài)方法

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p1 data"), 500);
})
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p2 data"), 1000);
})
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p3 data"), 1500);
})

const proArray = [p1, p2, p3];
async function asyncFn() {
  const list = await Promise.all(proArray);
  console.log(list); // ['p1 data', 'p2 data', 'p3 data']
}
asyncFn();

for await...of

一個數(shù)組中存儲多個Promise對象我們可以通過Promise.all獲取或者通過循環(huán)來等待其返回值, 我們使用循環(huán):

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p1 data"), 500);
})
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p2 data"), 1000);
})
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p3 data"), 1500);
})

const proArray = [p1, p2, p3];

async function asyncFn() {
  for (const pro of proArray) {
    // 這里不要忘記 await
    const res = await pro;
    console.log(res);
  }
}
asyncFn();

ES9開始有一個新語法就是for await..of可以自動等待每次循環(huán)的項

async function asyncFn() {
  for await (const item of proArray) {
    console.log(item);
  }
}
asyncFn();

參考:

總結(jié)

到此這篇關(guān)于JavaScript中Promise使用的文章就介紹到這了,更多相關(guān)JS Promise的使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JS獲取url參數(shù),JS發(fā)送json格式的POST請求方法

    JS獲取url參數(shù),JS發(fā)送json格式的POST請求方法

    下面小編就為大家分享一篇JS獲取url參數(shù),JS發(fā)送json格式的POST請求方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • js實現(xiàn)股票實時刷新數(shù)據(jù)案例

    js實現(xiàn)股票實時刷新數(shù)據(jù)案例

    下面小編就為大家?guī)硪黄猨s實現(xiàn)股票實時刷新數(shù)據(jù)案例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • js實現(xiàn)貪吃蛇游戲含注釋

    js實現(xiàn)貪吃蛇游戲含注釋

    這篇文章主要為大家詳細(xì)介紹了js實現(xiàn)貪吃蛇游戲含注釋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • 利用百度echarts實現(xiàn)圖表功能簡單入門示例【附源碼下載】

    利用百度echarts實現(xiàn)圖表功能簡單入門示例【附源碼下載】

    這篇文章主要介紹了利用百度echarts實現(xiàn)圖表功能簡單,結(jié)合簡單示例形式分析了echarts插件的圖標(biāo)繪制功能相關(guān)實現(xiàn)技巧,并附帶源碼供讀者下載參考,需要的朋友可以參考下
    2019-06-06
  • 第六篇Bootstrap表格樣式介紹

    第六篇Bootstrap表格樣式介紹

    這篇文章主要介紹了第六篇Bootstrap表格樣式介紹的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-06-06
  • 微信JS接口大全

    微信JS接口大全

    這篇文章主要為大家分享了最全面詳細(xì)的微信JS接口大全,希望對大家有幫助,感興趣的小伙伴們可以參考一下
    2016-08-08
  • javascript框架設(shè)計之類工廠

    javascript框架設(shè)計之類工廠

    這篇文章主要介紹了javascript框架設(shè)計之類工廠的相關(guān)資料,非常淺顯易懂,有需要的小伙伴可以查看下。
    2015-06-06
  • JS實現(xiàn)將對象轉(zhuǎn)化為數(shù)組的方法分析

    JS實現(xiàn)將對象轉(zhuǎn)化為數(shù)組的方法分析

    這篇文章主要介紹了JS實現(xiàn)將對象轉(zhuǎn)化為數(shù)組的方法,結(jié)合實例形式分析了javascript操作及轉(zhuǎn)換json數(shù)組相關(guān)實現(xiàn)技巧,需要的朋友可以參考下
    2019-01-01
  • 微信小程序input抖動問題的修復(fù)方法

    微信小程序input抖動問題的修復(fù)方法

    這篇文章主要給大家介紹了關(guān)于微信小程序input抖動問題的修復(fù)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • JSON字符串和對象相互轉(zhuǎn)換實例分析

    JSON字符串和對象相互轉(zhuǎn)換實例分析

    這篇文章主要介紹了JSON字符串和對象相互轉(zhuǎn)換的方法,結(jié)合實例形式分析了json格式數(shù)據(jù)的轉(zhuǎn)換方法,涉及javascript正則與字符串操作的相關(guān)技巧,需要的朋友可以參考下
    2016-06-06

最新評論