2016-02-25 17 views
16

Tính năng mới không đồng bộ/chờ đợi của TypeScript sử dụng lời hứa ES6. AngularJS sử dụng dịch vụ $q hứa hẹn với giao diện hơi khác một chút.

Có cách nào để sử dụng tính năng TypeScript async/await với dịch vụ $q hứa hẹn không?

+1

Yes. Vấn đề đầu tiên là tôi phải chuyển đổi mọi lời hứa đáp ứng từ ng-dịch vụ sang sử dụng đang chờ đợi nó. Vấn đề thứ hai là các lời hứa ES6 được tạo ra bởi biểu thức chờ đợi không bắt đầu chu kỳ tiêu hóa góc – Random

Trả lời

16

Sau đây là cách nó được thực hiện:

angular.module('your app') 
     .run(['$window', '$q', function($window, $q) { 
      $window.Promise = $q; 
     }]); 
+0

Cảm ơn bạn, nó gọn gàng hơn nhiều so với phiên bản của tôi. Tôi không biết rằng $ q dịch vụ có thể được sử dụng như là một nhà xây dựng tương thích với es6 hứa hẹn – Random

+1

Điều này làm việc, và tôi đang sử dụng nó trong một số dự án bây giờ. Nhưng tôi không thể không lay động cảm giác đó là nghịch ngợm. Thay thế đối tượng Promise toàn cầu bằng dịch vụ $ num góc có vẻ ... hackish. –

+2

Thay thế Lời hứa gốc với $ q có lẽ là điều tồi tệ nhất mà người ta có thể làm với ứng dụng. Chúng là những cách triển khai khác nhau về cơ bản, hoạt động khác nhau, điều này sẽ hủy hoại tất cả mã của bên thứ ba phụ thuộc vào 'Lời hứa'. Tuyên bố về cửa sổ $ 'hackish' $ là sai - không có vì Angular không có khả năng sử dụng cửa sổ gốc, nhưng vì DI là tốt. – estus

3

Tôi không nghĩ rằng bạn sẽ có thể sử dụng chúng trực tiếp. Nhưng nó phải là khá dễ dàng để chuyển đổi q hứa hẹn vào một lời hứa ++, một cái gì đó như thế này:

function Convert<T>(qPromise): Promise<T> 
{ 
    return new Promise<T>((resolve, reject) => 
    { 
     qPromise.then((result: T) => resolve(result), (e) => reject(e)); 
    }); 
}; 
+4

Vấn đề là trong trường hợp này, tôi phải bọc từng dịch vụ trả về $ q lời hứa. Ngoài ra, lời hứa ES6 không khởi tạo chu trình tiêu hóa góc. Vì vậy, trong trường hợp này, tôi phải gọi '$ apply' sau mỗi' await' – Random

1

Cuối cùng tôi đã sử dụng workaround sau:

declare var __awaiter: Function; 
(window as any).__awaiter = __awaiter; // set global __awaiter to avoid declaring default __awaiter in other files 
async() => { } // dummy async function to generate __awaiter code for current file 

angular.module('ts-awaiter', []).run(['$timeout', ($timeout: ng.ITimeoutService) => { 
    function wrap(func: Function) { 
     return function() { 
      func.apply(this, arguments); 
      $timeout(() => { }); // run angular digest 
     }; 
    } 

    var oldAwaiter = __awaiter; 
    (window as any).__awaiter = (thisArg: any, _arguments: any, P: Function, generator: any) => { 
     P = function (executor: Function) { 
      return new Promise<any>((resolve, reject) => { 
       resolve = wrap(resolve); 
       reject = wrap(reject); 
       executor(resolve, reject); 
      }); 
     }; 
     return oldAwaiter(thisArg, _arguments, P, generator); 
    }; 
}]); 

Comliper cho nguyên cảo 1.8 tạo __awaiter chức năng trong mỗi tập tin mà Nhà điều hành await được sử dụng. Tôi thay thế nó bằng cách triển khai thực hiện công cụ xây dựng tùy chỉnh Promise khởi tạo chu kỳ tiêu hóa sau mỗi cuộc gọi resolvereject. Dưới đây là cách sử dụng ví dụ: https://github.com/llRandom/ts-awaiter

+0

Chỉ vì tò mò việc xử lý này bị từ chối như thế nào? bắt khối? – Luis

+0

Có. Thêm một ví dụ vào kho lưu trữ – Random

+0

Điều này có thể dẫn đến việc tiêu hóa không cần thiết, và tiêu hóa là nút cổ chai phổ biến nhất cho hiệu suất ứng dụng AngularJS. Và giải pháp này không thể áp dụng cho mục tiêu TypeScript ES2017 ... bản địa không đồng bộ/chờ đợi đã có sẵn. – estus

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