1. 程式人生 > >for迴圈非同步呼叫介面,怎樣判斷資料已經返回完成?

for迴圈非同步呼叫介面,怎樣判斷資料已經返回完成?

在工作中遇到了一個for迴圈呼叫介面的例子:首先要根據一個叢集ID,去呼叫介面查詢此叢集下的所有“名稱空間”,接著再用for迴圈來一個個查詢所有“名稱空間”下的“例項”,eg:

<script type="text/javascript">
    namespaceService.getNamespaceList(clusterId,...(其它引數)).then(
        function( response ){
            var namespaceList = response.items;
            var  sensitiveWordFlag = false;
            for( var i = 0; i < namespaceList.length; i++){
                clusterService.getPods( namespaceList[i].name, ...(其它引數)).then(
                    function( res ){
                        for( var j = 0;j<res.length;j++ ){
                            if( res[j].name.test("abc") == true){
                                window.alert("含有敏感字元abc");
                                sensitiveWordFlag = true;
                                return;
                            }

                        }                       
                    }
                )
                if( !sensitiveWordFlag ){
                    window.alert("所有返回資料內容沒有敏感字元");
                }
            }
        }
    );
 </script>

大家應該看出問題了,最後那個函式裡面最後一個 if 的寫法是有問題的,因為介面的呼叫是非同步執行的,一個名稱空間的資料還沒有返回,它就先直接走進去了。那我們該如何改寫呢?也就是要加一個怎樣的判斷條件,才能控制它是在所有的介面資料都在執行完上一個 if 以後,再走這一個 if ?我們只需再加一個 變數即可:

<script type="text/javascript">
    namespaceService.getNamespaceList(clusterId,...(其它引數)).then(
        function( response ){
            var namespaceList = response.items;

            var sensitiveWordFlag = false;  // 敏感字元標識
            var count = 0; // 執行次數, 用於判斷是否遍歷完所有namespace

            for( var i = 0; i < namespaceList.length; i++) {

                // 如果之前有敏感字元,就不再遍歷
                if (sensitiveWordFlag) {
                    break;
                }

                clusterService.getPods( namespaceList[i].name, ...(其它引數)).then(
                    function( res ){
                        // 遍歷一個namespace ,count + 1
                        count++;

                        // 如果之前有敏感字元,就不再遍歷
                        if (sensitiveWordFlag) {
                            return;
                        }

                        // 判斷所有例項是否有敏感字元
                        for( var j = 0;j<res.length;j++ ){
                            if( res[j].name.test("abc") == true){
                                sensitiveWordFlag = true;
                                window.alert("含有敏感字元abc");
                                return; // break;
                            }           
                        }

                        // 當標識位是False,且計數等於namespace長度的時候,說明已經遍歷所有的namespace,也沒發現敏感字元
                        if( !sensitiveWordFlag && count == namespaceList.length ){
                            window.alert("所有返回資料內容沒有敏感字元");
                        }
                    }
                ); // getPods
            }

        }
    );
</script>

再來看一種實現,如果需要提示使用者和哪些例項衝突了,那麼你就需要將衝突的例項儲存到一個臨時變數裡。但你會發現需要窮盡所有的例項,才能確定衝突的例項。(效能問題,可想而知)

<script type="text/javascript">
    namespaceService.getNamespaceList(clusterId,...(其它引數)).then(
        function( response ){
            var namespaceList = response.items;

            var sensitiveWord = []; //用於記錄敏感的例項名稱
            var count = 0; // 執行次數, 用於判斷是否遍歷完所有namespace

            for( var i = 0; i < namespaceList.length; i++) {

                clusterService.getPods( namespaceList[i].name, ...(其它引數)).then(
                    function( res ){
                        // 遍歷一個namespace ,count + 1
                        count++;

                        // 判斷所有例項是否有敏感字元
                        for( var j = 0;j<res.length;j++ ){
                            if( res[j].name.test("abc") == true){
                                // 儲存敏感的例項名稱
                                sensitiveWord[sensitiveWord.length] = res[j].name;
                            }           
                        }

                        // 當遍歷完所有namespace時,判斷sensitiveWord
                        if( count == namespaceList.length ){
                            if (sensitiveWord.length > 0){
                                window.alert("含有敏感字元abc");
                                // sensitiveWord儲存的值,是所有敏感例項的名稱
                            } else {
                                window.alert("所有返回資料內容沒有敏感字元");
                            }
                        }
                    }
                ); // getPods
            }

        }
    );
</script>