Promise.all()的使用以及js處理機制


本文涉及到的知識:

  1. Promise,all()的使用
  2. js處理機制
  3. reduce的用法
  4. map的用法
  5. 同步異步

需求:

一個頁面中需要用到多個字典數據。用於下拉選項,同時,需要將其保存為json格式。以便於key,value的相互轉換。

data(){
    return{
        codeList:[]
    }
},
    
computed:{
    	confPropertyTypeOptions() {
            return this.codeList.length ? this.codeList[0].options : [];
        },

        configurationTypeOptions() {
            return this.codeList.length ? this.codeList[1].options : [];
        },
},
    
created(){
		let codeType = ['confPropertyType', 'configurationType'];
        let arrTemp = [];
        let promiseList = codeType.map(type => getCode(type));
        Promise.all(promiseList)
            .then(res => {
                // arrTemp = res.map(v => {
                //     if (Array.isArray(v.data) && v.data.length > 0) {
                //         const arr = v.data;
                //         let json = {};
                //         for (let i in v.data) {
                //             let item = v.data[i];
                //             json[item.ctCode] = item.ctName;
                //         }
                //         return {
                //             options: arr,
                //             json: json,
                //         };
                //     }
                //     return { options: [], json: {} };
                // });

                arrTemp = res.reduce((prev, current) => {
                    if (
                        Array.isArray(current.data) &&
                        current.data.length > 0
                    ) {
                        const arr = current.data;
                        let json = {};
                        for (let i in current.data) {
                            let item = current.data[i];
                            json[item.ctCode] = item.ctName;
                        }
                        prev.push({
                            options: arr,
                            json: json,
                        });
                        return prev;
                    }
                }, []);
                this.codeList = arrTemp;
            })
            .catch(() => {
                this.$message.error('查詢類型失敗');
            });
    }

getCode(codetype)是一個post請求。通過字典類型獲取字典數據。

最開始是這么實現的:

created() {
	let codeType = ['confPropertyType', 'configurationType'];
    codeType.forEach(code => {
        getCode(code).then(res => {
            if (
                Array.isArray(res.data) &&
                res.data.length > 0
            ) {
                const arr = res.data;
                let json = {};
                for (let i in res.data) {
                    let item = res.data[i];
                    json[item.ctCode] = item.ctName;
                }
                this.codeList.push({
                    options: arr,
                    json: json,
                });  
            })
    })
}

坑1:然而初始化頁面的時候報錯:compute里邊的options值獲取不到。為什么呢?

因為:compute屬性里的this.codeList.length在第一次push的時候就不為0了,所以會報錯。this.codeList.length此時的長度為1。

優化后:

用一個臨時數組去保存一下請求拿到的值,等foreach完成后再去賦值給codeList變量。

created() {
    let arrTemp = [];
	let codeType = ['confPropertyType', 'configurationType'];
    codeType.forEach((code,index) => {
        getCode(code).then(res => {
            if (
                Array.isArray(res.data) &&
                res.data.length > 0
            ) {
                const arr = res.data;
                let json = {};
                for (let i in res.data) {
                    let item = res.data[i];
                    json[item.ctCode] = item.ctName;
                }
                arrTemp.push({
                    options: arr,
                    json: json,
                });  
            })
        if(index === codeType.length-1){
            this.codeList = arrTemp
        }
    })
}

坑2:然后還是報錯,但是我們的思路是正確的,就是等兩次請求完成后,再去處理這個結果。

這里是因為getCode()是一個異步方法,這兩次異步完成的時間是不確定的,有可能你的第一個getCode(異步)還沒返回結果,forEach(同步)已經完事了。

需要了解一下js的異步處理機制。你的代碼是一行行往下執行的,然后遇到一個異步方法(或者異步塊),程序會把這個異步放到一個異步隊列中,程序繼續順序執行,同時,異步隊列中的塊也在執行。不過它什么時候結束,你並不知道。

這是Promise方法就發揮作用了。如我們最開始的實現。

let promiseList = codeType.map(type => getCode(type));

這時的promiseList是一個擁有兩個Promise對象元素的數組

promiseList = [new Promise(),new Promise()]

Promise.all(promiseList),這兩個post請求完成后,在.then()中可以處理res數據。

然后就是res.map()與res.reduce()的用法與區別了。

reduce(handler,target)

1.handler是一個方法 (prevent,current) => {return prevent}

​ prevent是我們處理后的結果,用於返回,

​ current是當前累加器的元素

2.target是我們的目標結果,可以是array,string,obj等


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM