2013-06-25 33 views
5

Trong jQuery, nếu bạn mắc lỗi trong phương thức gọi lại ajax, bạn sẽ nhận được thông báo lỗi điều khiển thích hợp và stacktrace.Dojo - Tham khảoMỗi ngoại lệ trong lời hứa bị nuốt

$.get("https://api.github.com/users/octocat/orgs", function() { 
    var a = FAIL; 
}); 

Tuy nhiên, trong dojo sử dụng dojo/request/xhr có vẻ như những sai lầm ngớ ngẩn này đang được nuốt hoàn toàn. Điều duy nhất trong bảng điều khiển của tôi khi tôi chạy này là "sau đó" và "luôn luôn".

require(["dojo/request/xhr" ], function(xhr) { 
    var promise = xhr.get("https://api.github.com/users/octocat/orgs"); 
    promise.then(function(data) { 
     console.log('then'); 
     var a = FAIL; 
     console.log('goodbye'); 
    }, function() { 
     console.log('error'); 
    }); 
    promise.otherwise(function() { 
     console.log('otherwise'); 
    }); 
    promise.always(function() { 
     console.log('always'); 
    }); 
}); 

Sử dụng thẻ dojo.xhrGet không được chấp nhận, vấn đề được cải thiện rất ít. Tôi nhận được thông console lỗi và xử lý lỗi của tôi được gọi nhưng nó chỉ nói "ReferenceError {}" và cung cấp cho tôi với một vết đống mà không bao giờ trỏ tới một hàm tôi sở hữu:

dojo.xhrGet({ 
    url: "https://api.github.com/users/octocat/orgs", 
    load: function() { 
     console.log('dojo.xhrGet.load'); 
     var a = FAIL; 

     console.log('goodbye dojo.xhrGet.load'); 
    }, 
    error: function() { 
     console.log('dojo.xhrGet.error'); 
    }, 
    handle: function() { 
     console.log('dojo.xhrGet.handle'); 
    } 
}); 

Khi viết một chương trình chúng tôi thực hiện sai lầm, thật tuyệt khi chúng tôi có các công cụ như công cụ phát triển chrome để chỉ cho chúng tôi những lỗi đó. Thời gian cần để tìm lỗi khi bạn có thể thấy một stacktrace và thông báo lỗi rõ ràng là nhanh hơn nhiều nếu bạn không nhận được phản hồi. Tôi không nhận được phản hồi trong dojo, tôi không thể tin rằng một thư viện phổ biến như vậy có thể hoạt động theo cách này. Tôi đang làm gì sai?

Trả lời

4

Sự hiểu biết về những lời hứa mà bạn được thừa kế từ jQuery cơ bản là khác nhau đối với một người khác (kiểm tra Promises/a + triển khai) có. Đối với phần còn lại của câu trả lời này, tôi sẽ nói về lời hứa/a + lời hứa tương thích. Dojo's Deferred thực sự không phải là một + tuân thủ, nhưng nó đủ gần mà tất cả mọi thứ tôi thảo luận ở đây áp dụng như nhau tốt.

Lời hứa là không thay đổi, bạn không thể thay đổi trạng thái lời hứa bằng cách gọi then. Một lời hứa đại diện cho một giá trị cuối cùng, nó sẽ là vô nghĩa để có thể thay đổi lời hứa bằng cách nói "một khi giá trị đã sẵn sàng, làm điều này". Vì vậy, hy vọng điều đó giải thích lý do tại sao trình xử lý lỗi của bạn không được gọi, nhưng ý tưởng cơ bản, về việc bắt lỗi, vẫn hoàn toàn có thể xảy ra. Bạn chỉ cần sử dụng các giá trị trả lại. Khi bạn gọi then theo lời hứa, nó sẽ trả về một lời hứa mới và (hầu như luôn luôn) khác nhau. Lời hứa mới này rất đặc biệt, nếu bản gốc được giải quyết, và người xử lý thành công mà bạn đã vượt qua được gọi, và điều đó trả về một cái gì đó, rằng cái gì đó sẽ là giá trị độ phân giải của lời hứa thứ hai.

Tương tự, nếu trình xử lý lỗi (trên lời hứa đầu tiên) được kích hoạt, và hàm đó trả về một cái gì đó, thì cái gì đó sẽ là giá trị độ phân giải của lời hứa thứ hai. Điều tương tự cũng đúng đối với các lỗi được ném, chúng được chuyển tới trình xử lý lỗi (của lời hứa thứ hai!).

Vì vậy, đây là mẫu mã đầu tiên bạn viết bằng một lời hứa thêm/a + cách:

require(["dojo/request/xhr" ], function(xhr) { 
    var promise = xhr.get("https://api.github.com/users/octocat/orgs"); 
    promise.then(function(data) { 
     console.log('then'); 
     var a = FAIL; 
     console.log('goodbye'); 
    }, function() { 
     console.log('error'); 
    }).then(null, function() { 
     console.log('otherwise'); 
    }); 

    promise.always(function() { 
     console.log('always'); 
    }); 
}); 

tôi không thực sự hiểu những gì bạn muốn làm gì với luôn chức năng, vì vậy tôi đã không chắc chắn nơi để đặt cái đó. Về chủ đề ngăn xếp cuộc gọi, tôi khuyên bạn nên kiểm tra thư viện lời hứa Q có hỗ trợ chồng không đồng bộ nâng cao vô cùng.

+0

Đây là lời giải thích tuyệt vời về những gì đang xảy ra. Dưới đây là một thay đổi nhỏ cho mã của bạn cung cấp một stacktrace quá: http://jsfiddle.net/5rHM6/ Thật không may ngăn xếp dấu vết không trỏ đến dòng chính xác (nó trỏ đến dòng console.error). Vì vậy, nếu bạn muốn bắt lỗi, đây là câu trả lời đúng; nếu bạn muốn tìm lỗi, tôi có xu hướng chọn câu trả lời của tôi. Tuy nhiên có vẻ như nếu bạn bắt gặp lỗi, thiết bị bị triệt tiêu, do đó bạn không thể đạt được kết quả tốt nhất của cả hai thế giới. –

+0

Bạn nói đúng, đó là dịch vụ thông báo vượt qua ("có lỗi") trái ngược với dịch vụ báo lỗi đầy đủ với dấu vết ngăn xếp. Tôi sẽ yêu cầu bạn kiểm tra thư viện Q, đó là thư viện không đồng bộ tốt nhất mà tôi biết và chắc chắn họ sẽ giải quyết vấn đề này. –

4

Trong dojoConfig set useDeferredInstrumentation: true. Đây là an example.

 <script> 
      var dojoConfig = { 
       useDeferredInstrumentation: true 
      }; 
     </script> 
     <script src="js/lib/dojo/dojo.js.uncompressed.js"></script> 

này đưa ra một thông báo lỗi và stacktrace đầu ra khá chức năng trên console.error:

ReferenceError {} "ReferenceError: FAIL is not defined 
    at http://fiddle.jshell.net/gNdCb/2/show/:25:17 
    at signalListener (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14205:21) 
    at signalWaiting (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14196:4) 
    at resolve (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14360:5) 
    at signalDeferred (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14249:15) 
    at signalListener (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14220:6) 
    at signalWaiting (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14196:4) 
    at resolve (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14360:5) 
    at signalDeferred (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14249:15) 
    at signalListener (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14226:4) 
    ---------------------------------------- 
    rejected at signalDeferred (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14252:15) 
    at signalListener (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14223:5) 
    at signalWaiting (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14196:4) 
    at resolve (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14360:5) 
    at signalDeferred (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14249:15) 
    at signalListener (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14220:6) 
    at signalWaiting (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14196:4) 
    at resolve (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14360:5) 
    at signalDeferred (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14249:15) 
    at signalListener (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14226:4) 
    ---------------------------------------- 
Error 
    at Promise.then.promise.then (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:14420:24) 
    at http://fiddle.jshell.net/gNdCb/2/show/:23:13 
    at runFactory (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:1117:43) 
    at execModule (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:1245:5) 
    at http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:812:7 
    at guardCheckComplete (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:1260:5) 
    at contextRequire (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:811:6) 
    at req (http://ajax.googleapis.com/ajax/libs/dojo/1.9.0/dojo/dojo.js.uncompressed.js:137:11) 
    at http://fiddle.jshell.net/gNdCb/2/show/:21:1" 
+0

Tất nhiên sẽ rất tuyệt khi có thể bắt hoặc xử lý các lỗi này trong một cái gì đó như window.onerror. Bất kỳ đề xuất? –

+0

xem câu trả lời của @David McMullin để bắt lỗi –

0

Tôi có những nhu cầu rất cụ thể trong đó tôi cần ngoại lệ để đạt đến điều khoản bắt gốc mà trình duyệt thực hiện. Nevermind lý do tại sao tôi cần này, Nhưng tôi đã sử dụng một cái gì đó như thế này:

function scream(func) { 
    return function() { 
     var args = arguments; 
     setTimeout(function(){ 
      func.apply(null, args); 
     }, 0); 
    }; 
} 

Sau đó, để sử dụng nó

var promise = xhr.get("https://api.github.com/users/octocat/orgs"); 
promise.then(scream(function(data) { 
    //do stuff 
})); 

Bằng cách sử dụng setTimeout, bạn thực hiện các chức năng trên hàng đợi trình duyệt sự kiện, làm cho nó không thể cho dojo nuốt ngoại lệ của bạn. Nhưng, nói chung đây là một giải pháp xấu vì:

  • nó thay đổi một phần của stack trace
  • nó thay đổi một phần của mã của bạn mà trước đó được thực hiện đồng bộ để đồng bộ, có thể thay đổi hành vi chương trình
  • bạn không thể chuỗi nhiều .then() hứa hẹn các đối tượng với giá trị trả về, đó là một trong những điều thực sự tốt đẹp về lời hứa.

Dù sao, tôi chỉ trình bày nó dưới dạng tùy chọn.

Các vấn đề liên quan