2011-12-19 33 views
9

Trong khi phát triển một ứng dụng PhoneGap trên điện thoại di động, tôi gặp phải một vấn đề thú vị. Tôi cần truy vấn khoảng 10 mục dữ liệu từ cơ sở dữ liệu (thông qua API API PhoneGaps) ... Giống như nhiều API javascript, điều này là không đồng bộ. Khi bạn thực hiện truy vấn của mình, bạn sẽ chuyển sang trình xử lý "thành công".Nhận hành vi đồng bộ trong javascript?

Bây giờ, tùy chọn của tôi trong trường hợp này sẽ là phương thức truy vấn đồng bộ chỉ trả lại khi hoàn tất. Sau đó, tôi có thể viết đoạn mã thẳng để truy vấn từng mục trong số 10 mục 1.

Do tính chất không đồng bộ của PhoneGap (thực sự, tôi thấy điều này trên khắp JS tuy nhiên) Tôi đã buộc phải viết một con thú trông như thế này:

db.query("SELECT...", success() { 
    db.query("SELECT...", success() { 
     db.query("SELECT...", success() { 
      db.query("SELECT...", success() { 
       db.query("SELECT...", success() { 
       } 
      } 
     } 
    } 
} 

Và đây chỉ là một nửa như sâu như tôi đã phải đi (và đơn giản hóa rất nhiều ...) ... Khi nào, có tôi đã sử dụng SQLite trong C, tôi có thể chỉ đơn giản là thực hiện một cái gì đó như:

db.query("SELECT...", resultA); 
db.query("SELECT...", resultB); 
db.query("SELECT...", resultC); 
db.query("SELECT...", resultD); 
db.query("SELECT...", resultE); 

dường như với tôi rằng cách tiếp cận xử lý thành công là rất tốt khi bạn chỉ phải đi 1 hoặc 2 cấp độ sâu ... Nhưng, hoàn toàn sụp đổ khi bạn cần thêm tha n ...

Thư viện của họ, hoặc tính năng của thư viện ở đâu đó có thể làm việc này dễ dàng hơn không?

Trả lời

7

Đây là một vấn đề rất phổ biến trong cộng đồng mà nhiều mẫu and libraries đã phát sinh để chống lại nó.

Yêu thích của tôi là lời hứa. Tôi đã trình bày về lời hứa như một giải pháp cho vấn đề async tại một vài sự kiện; bạn có thể xem các trang trình bày của tôi trên SlideShare: Callbacks, Promises, and Coroutines (oh my!): The Evolution of Asynchronicity in JavaScript. Nó cũng giải thích lý do tại sao asynchronicity là cần thiết --- trong ngắn hạn, bởi vì JavaScript là đơn luồng.

Đối với ví dụ cụ thể bạn đưa ra, hãy xem trang trình bày 53 và vùng lân cận. Tóm lại, giả sử db.query trở một lời hứa, nó sẽ trông giống như:

db.query("SELECT...") 
    .then(function (a) { 
    return db.query("SELECT..." + a); 
    }) 
    .then(function (b) { 
    return db.query("SELECT..." + b); 
    }) 
    .then(function (c) { 
    return db.query("SELECT..." + c); 
    }) 
    .then(function (d) { 
    return db.query("SELECT..." + d); 
    }) 
    .then(function (e) { 
    return db.query("SELECT..." + e); 
    }); 

Tất nhiên nó trở nên đẹp hơn rất nhiều nếu bạn không cần phải sử dụng các kết quả của một truy vấn cho các tiếp theo:

Q.all([ 
    db.query("SELECT..."), 
    db.query("SELECT..."), 
    db.query("SELECT..."), 
    db.query("SELECT..."), 
    db.query("SELECT...") 
]).spread(function (a, b, c, d, e) { 
    // ... 
}); 
+0

Thư viện thú vị. Thật tốt khi biết câu trả lời của tôi không phải là điên rồ, vì đó là mẫu mã cuối cùng bạn đang làm. +1 – cdeszaq

3

Một cách đơn giản hóa cơ bản là đặt các truy vấn trong danh sách và có cùng một trình xử lý thành công, chỉ cần gọi truy vấn tiếp theo trong danh sách. Bạn sẽ cần phải giữ một con trỏ đến truy vấn hiện đang thực hiện, nhưng nó sẽ sạch hơn (ít nhất là từ cách mã trông) cung cấp cho bạn hành vi đồng bộ.

Thao tác này sẽ hoạt động đối với mọi đóng vì bạn chỉ có thể đặt giá trị danh sách thành một loạt các đoạn mã và sau đó thực thi tất cả các thứ tự theo thứ tự.

3

Nếu nó chỉ làm tổ làm phiền bạn, chỉ đơn giản là chuỗi các phương pháp theo tên:

function success1() { 
    // do stuff to handle success 
    db.query("SELECT...", success2); 
} 

function success2() { 
    db.query("SELECT...", success3); 
} 

function success3() { 
    db.query("SELECT...", success4); 
} 

function success4() { 
    // do something 
} 

db.query("SELECT...", success1); 

này sẽ không hoạt động nếu bất kỳ của những bộ xử lý thành công bên trong cần truy cập vào một cái gì đó đã được xác định trong phạm vi từ vựng của nó, nhưng đó có thể không phải là trường hợp (và ngay cả khi nó là, bạn vẫn có thể vượt qua những giá trị đó như là các đối số cho hàm tiếp theo trong chuỗi).

1

Có một Khung nguồn mở biết là Siminov Hybrid, nó cung cấp ORM cho cả Native (Java) và Web (JavaScript).Bằng cách sử dụng điều này bạn có thể làm cho tất cả các hoạt động cơ sở dữ liệu đồng bộ, bởi vì khung này sử dụng kênh truyền thông được cung cấp bởi Android là Đồng bộ.

Rất dễ tích hợp PhoneGap với khung này. Sử dụng điều này, bạn có thể làm việc với cả ORM gốc và Web ORM cùng một lúc.

http://siminov.github.io/android-hybrid

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