日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Promise同時獲取n個接口數據的幾種方式

作者:qq_42750608 更新時間: 2023-10-10 編程語言

先使用Promise封裝, 以便使用它的鏈式調用方法:

const url1 = './data1.json'

const url2 = './data2.json'

const url3 = './data3.json'


const getData = async(url) => {
    return new Promise((resolve, reject)=> {
        axios({
            method: 'get',
            url,
            data: {},
        })
        .then(res=> {
            resolve(res)
        })
        .catch(err=> {
            reject(err)
        })
    })
}

1.鏈式調用:

getData(url1)
.then(data1 => {
    console.log(data1)
    return getData(url2)
})
.then(data2 => {
    console.log(data2)
    return getData(url3)
})
.then(data3 => {
    console.log(data3)
})
.catch(err => console.log(err));

2. asyc await

const data1 = await getData(url1)
const data2 = await getData(url2)
const data3 = await getData(url3)

console.log(data1, data2, data3)

3.Promise.allSettled

mock數據, 想要成功的數據可以Promise.resolve({a: 1}), mock失敗的返回數據:?Promise.reject({err1: 1})

const f1 = getData(url1)
const f2 = Promise.reject({err2: 2})
const f3 = Promise.reject({err3: 3})
Promise.allSettled([f1, f2, f3])
.then(res => {
  // 成功和失敗的數據都會返回, 可以根據需要篩選需要的數據
  console.log(res, 'allSettled-success')
})
.catch(err => {
  // catch沒有catch到接口返回的錯誤數據, 全部都返回到then去了
  console.log(err, 'error')
})
.finally(() => {
  // 不管成功還是失敗都會走到finally
  console.log('finally')
})

4.Promise.all

Promise.all([f1, f2, f3])
.then(res => {
  // 全部都是返回成功的數據才會打印
  console.log(res, 'all-success')
})
.catch(err => {
  // 只要有一個失敗就會打印, 剩下的失敗就不會打印了
  console.log(err, 'error')
})
.finally(()=> {
  // 不管成功還是失敗都會走到finally
  console.log('all--finally')
})

5.Promise.race只有第一個resolve或者reject的數據返回了, 其余的不返回

Promise.race([f1, f2, f3])
.then(res => {
  // 如果第一個返回數據是resolve的, 就打印
  console.log(res, 'race-success')
})
.catch(err => {
  // 如果第一個返回數據reject的, 就打印
  console.log(err, 'race-error')
})
.finally(()=> {
  // 不管第一個返回的是成功還是失敗都會走到finally
  console.log('race--finally')
})

6.Promise.all如果想要成功結果和失敗結果一起返回,則

function onReject(err) {
  return (err);
}
const f1 = () => getData(url1).catch(onReject)
const f2 = () => getData(url2).catch(onReject)
const f3 = () => getData(url3).catch(onReject)

Promise.all([f1, f2, f3])
.then(res => {
  console.log(res, 'all-success')
})
.catch(err => {
  console.log(err, 'error')
})
.finally(()=> {
  // 不管成功還是失敗都會走到finally
  console.log('all--finally')
})

7.Promise和setTimeout模擬并發場景:

function onReject(err) {
  return (err);
}

const f1 = () => getData(url1).catch(onReject)
const f2 = () => getData(url2).catch(onReject)
const f3 = () => getData(url3).catch(onReject)
const f4 = ()=> getData(url4).catch(onReject)
const f5 = () => getData(url5).catch(onReject)
const f11 = () => getData(url11).catch(onReject)
const f12 = () => getData(url12).catch(onReject)
const f13 = () => getData(url13).catch(onReject)
const f14 = ()=> getData(url14).catch(onReject)
const f15 = () => getData(url15).catch(onReject)


/**
 * 代碼的核心思路為:

1.先初始化 promiseListLimit 個 promise 實例,將它們放到 executing 數組中
2.使用 Promise.race 等待這 promiseListLimit 個 promise 實例的執行結果
3.一旦某一個 promise 的狀態發生變更,就將其從 executing 中刪除,然后再執行循環生成新的 promise,放入executing 中
4.重復2、3兩個步驟,直到所有的 promise 都被執行完
5.最后使用 Promise.all 返回所有 promise 實例的執行結果
 */
const concurrencyPromisePool = async (
  promiseListLimit,
  promiseArr,
  mockTimeoutDataFn
) => {
  const allPromiseArr = []; // 用于存放所有的promise實例
  const executing = []; // 用于存放目前正在執行的promise
  for (let index = 0; index < promiseArr.length; index++) {
    const promise = promiseArr[index];
    const mockPromise = mockTimeoutDataFn(promise, index); // 回調函數返回的必須是promise,否則需要使用Promise.resolve進行包裹
    allPromiseArr.push(mockPromise);
    if (promiseListLimit <= promiseArr.length) {
      // then回調中,當這個promise狀態變為fulfilled后,將其從正在執行的promise列表executing中刪除
      const executingItem = mockPromise.then(() =>
        executing.splice(executing.indexOf(executingItem), 1)
      );
      executing.push(executingItem);
      console.log(`并發接口數量: ${executing.length}`);
      if (executing.length >= promiseListLimit) {
        // 一旦正在執行的promise列表數量等于限制數,就使用Promise.race等待某一個promise狀態發生變更,
        // 狀態變更后,就會執行上面then的回調,將該promise從executing中刪除,
        // 然后再進入到下一次for循環,生成新的promise進行補充
        await Promise.race(executing);
      }
    }
  }
  return Promise.all(allPromiseArr);
};

// mock有1s延遲時間的promise, 方便查看并發的效果
const timeout = (promiseFn, i) => {
  console.log("開始--", i);
  return new Promise((resolve) =>
    setTimeout(() => {
      console.log("結束--", i);
      return resolve(promiseFn());
    }, 1000)
  );
};

const getConcurrencyPromise = async () => {
  try {
    const res = await concurrencyPromisePool(
      2,
      [f1, f2, f3, f4, f5, f11, f12, f13, f14, f15],
      timeout
    );
    console.log(res);
  } catch (error) {
    console.log(error, "errrrrr");
  }
};

getConcurrencyPromise();

并發方法可以用于多種場景,比如大文件分片上傳,要求并發,每次可以傳多片的情形

原文鏈接:https://blog.csdn.net/qq_42750608/article/details/133222216

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新