2016-03-09 50 views
0

我有一個index.json文件,該文件返回需要加載的其他N JSON文件的列表。他們需要使用不同的方法加載,這樣當他們全部加載時,我可以一次處理它們。jQuery加載未知數量的JSON文件與錯誤處理

附加JSON文件中的每一個都可能存在或不存在於服務器上。

我用下面的方法來加載數據,在服務器上實際存在的所有文件的正常工作:

$.getJSON('index.json').then(function (response) { 
    var files = response.files; 
    $.when 
    .apply(null, getDeferreds(files)) 
    .done(function() { 
      //process the files 
    }) 
    }); 
}); 

function getDeferreds(files) { 
    var deferreds = [], i; 
    for (i in files) { 
     //file type 1 
     deferreds.push(
      $.getJSON(files[i] + '_1.json') 
      .then(function (response) { 
       //do something 
      }) 
     ); 
     //file type 2 
     deferreds.push(
      $.getJSON(files[i] + '_2.json') 
      .then(function (response) { 
       //do something 
      }) 
     ); 
    } 
    return deferreds; 
}; 

這種做法的偉大工程,但是.... 當任何文件缺失,即somefile_2.json(有時索引將在文件實際存在於服務器上之前創建),整個過程失敗並且沒有數據正在被檢索。

$.getJson ($.get)我可以用.fail()方法檢測錯誤,但是這並不妨礙通話的失敗,.done()永遠不會被調用。

我該如何重構這個方法,使.done()方法始終有效,即使有些文件丟失了?

+0

嘗試將[第二個函數](https://api.jquery.com/deferred.then/#deferred-then-doneCallbacks-failCallbacks)傳遞給'.then',以返回失敗請求的佔位符(空對象) ,像'.then(function()...,function(){return {};});' –

+0

這與'.fail()'有相同的效果。它檢測到404錯誤,但仍然導致整個過程失敗。 – Yani

回答

1

事實證明,解決方案比我想象的要簡單。

我的猜測是,在調用失敗的過程中,延遲對象沒有被正確解析。

只需將return $.Deferred().resolve();添加到失敗回調中就行了。

發佈的情況下,錯誤處理一個完整的解決方案。它可以幫助別人:

$.getJSON('index.json').then(function (response) { 
    var files = response.files; 
    $.when 
    .apply(null, getDeferreds(files)) 
    .done(function() { 
      //process the files 
    }) 
    }); 
}); 

function getDeferreds(files) { 
    var deferreds = [], i; 
    for (i in files) { 
     deferreds.push(
      $.getJSON(files[i]) 
       .then(function (response) { 
        //do something 
       }, function() { 
        return $.Deferred().resolve([]); 
       }) 
     ); 
    }; 
    return deferreds; 
}; 
0

你寫什麼看起來不錯,提供do something包括return語句,以進一步提供數據下的諾言鏈(在主叫方) 。

你可能會考慮一些整理,並「切蛋糕」不同,方法是:在子功能

  • 在調用者進行傳遞的數據都處理

    • 聚集承諾

    這是一個偏好問題,但我可能會選擇寫:

    $.getJSON('index.json').then(function (response) { 
        return getFileData(response.files); 
    }).then(function(dataArray) { 
         // `dataArray` is an array of data items 
         // Do all processing here 
        }); 
    }); 
    
    function getFileData(files) { 
        var promises = files.map(function(file) { 
         return $.getJSON(file) 
         .then(null, // No processing here 
         function() { 
          return $.when([]); // $.when(value) is a useful shorthand for $.Deferred().resolve(value) 
         }); 
        }); 
        // By aggregating the promises here, caller(s) can be delivered an array of data items, wrapped in a single promise. 
        return $.when.apply(null, promises).then(function() { 
         return Array.prototype.slice.call(arguments); //convert function's `arguments` to a proper array 
        }); 
    }; 
    

    當然,如果getFileData()不會從別處被調用,你可以在調用者中做所有事情。