Nếu bạn chỉ muốn đợi giá trị cuối cùng, runTransactionBlock:andCompletionBlock:
là phương pháp bạn muốn xem. Dưới đây là một số mã mẫu:
[upvotesRef runTransactionBlock:^FTransactionResult *(FMutableData *currentData) {
NSNumber *value = currentData.value;
if (currentData.value == [NSNull null]) {
value = 0;
}
[currentData setValue:[NSNumber numberWithInt:(1 + [value intValue])]];
return [FTransactionResult successWithValue:currentData];
} andCompletionBlock:^(NSError *error, BOOL committed, FDataSnapshot *snapshot) {
if (error) {
NSLog(@"Error: %@", error);
}
if (committed) {
NSLog(@"Data committed");
}
NSLog(@"Final Value: %@", snapshot.value);
}];
Giá trị cuối cùng đó, snapshot.value
là nơi bạn có thể nhận giá trị cuối cùng. Đó là cùng loại FDataSnapshot
mà bạn nhận được nếu bạn sử dụng observeEventType:withBlock:
Nếu xảy ra sự cố, bạn sẽ nhận được error
.
Nếu dữ liệu của bạn được cam kết, committed
sẽ YES. Nếu bạn trở [FTransactionResult abort]
trong khối giao dịch của bạn thay vì [FTransactionResult successWithValue:]
, committed
sẽ NO.
Điều này có nghĩa, nếu bạn đọc truy cập vào 4 và cố gắng cập nhật nó. Bạn có thể thử cập nhật bộ đếm cùng lúc với người khác. Nếu bạn nhận được trong đầu tiên, snapshot.value
sẽ là 5. Nếu bản cập nhật của người khác nhận được trước khi bạn làm, các snapshot.value
sẽ là 6.
Bạn có thể muốn nhận được lên đến 6 không có vấn đề người upvoted đầu tiên. Để làm điều này, bạn cần phải thêm một người quan sát. Mã cho rằng có thể trông giống như:
[upvotesRef observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
NSLog(@"New Value: %@", snapshot.value);
}];
Với điều này, bạn không cần khối hoàn thành để tìm hiểu giá trị cuối cùng vì mỗi lần các khối giao dịch, khối người quan sát sẽ cháy. Trong kịch bản ví dụ trên, nó sẽ cháy một lần cho 5 và một lần cho 6 bất kể ai upvoted đầu tiên. Bạn cần khối hoàn thành nếu bạn muốn tìm hiểu xem giao dịch cụ thể của bạn có thành công hay không và không chỉ là giá trị tại vị trí đó ngay bây giờ.
Và, chỉ để được hoàn chỉnh, có thêm một phương pháp gọi là runTransactionBlock:andCompletionBlock:withLocalEvents:
. Nếu những người khác cũng đang viết thư cho cùng một vị trí, khối giao dịch có thể chạy nhiều lần. Điều này xảy ra nếu nó phát hiện ra rằng nó đang chạy trên dữ liệu cũ. Khi nó chạy thành công trên dữ liệu mới, nó sẽ gọi khối hoàn thành. Tuy nhiên, bạn sẽ thấy rằng mỗi khi nó chạy, nó sẽ kích hoạt bất kỳ khối quan sát nào tại vị trí đó. Nếu bạn không muốn điều này xảy ra, bạn phải vượt qua NO để withLocalEvents:
. Firebase của bạn sẽ kích hoạt các sự kiện tại vị trí đó bất cứ khi nào một văn bản được xác nhận đi qua, nhưng các ghi tạm thời của giao dịch địa phương của bạn, chưa được xác nhận, sẽ không.
Nhìn lại ví dụ mà bạn và một người khác đang cố gắng để upvote cùng một lúc. Theo mặc định, người quan sát sẽ kích hoạt ngay khi bạn cố cập nhật số đếm từ 4 đến 5. Giao dịch thực tế có thể không thành công vì người khác đã đẩy số lượng upvote từ 4 lên 5 cùng một lúc. Khối giao dịch của bạn sau đó sẽ chạy lại với dữ liệu mới, 5 và thấy rằng nó sẽ đẩy số lượng lên 6. Với sự kiện cục bộ được đặt thành KHÔNG, người quan sát sẽ kích hoạt sau khi máy chủ cho phép bạn biết ai đó đã đẩy số lượng upvote từ 4 đến 5 và không phải khi bạn cố gắng cập nhật số đếm từ 4 đến 5.
Đây không phải là vấn đề lớn với những thứ đơn giản như upvotes mà mọi người chỉ tăng, nhưng nếu bạn có khả năng đẩy dữ liệu khác người dùng, bất kỳ người quan sát nào ở vị trí đều có thể thấy dữ liệu nhảy xung quanh trước khi cuối cùng giải quyết.
Câu trả lời này sẽ được thêm vào tài liệu API Firebase ... không có tính năng đùa. – Reed
Thành thật mà nói, nó giải thích nó một cách hoàn hảo. Chúc mừng anh em –
@katfang nếu bạn có thể viết tương đương cho Swift, nó sẽ rất hữu ích. Cảm ơn nhiều – bibscy