how to chain multiple promises into a single transaction in Firebase

时间:2016-07-11 22:33:49

标签: javascript firebase firebase-realtime-database

A few months back Firebase implemented promises in the database.

In that blog post there is an example of using a single transaction with promises:

var article;
var articleRef = ref.child('blogposts').child(id);
articleRef.once('value').then(function(snapshot) {
  article = snapshot.val();
  return articleRef.child('readCount').transaction(function(current) {
    return (current || 0) + 1;
  });
}).then(function(readCountTxn) {
  renderBlog({
    article: article,
    readCount: readCountTxn.snapshot.val()
  });
}, function(error) {
  console.error(error);
});

Is it possible to chain multiple promises into a single transaction to be able to erase data only if everything can be erased?

1 个答案:

答案 0 :(得分:5)

Do you actually need a transaction or just an atomic operation? You can execute atomic operations on multiple paths simultaneously that will fail if something goes wrong with one of them (ie erase which is a write operation):

var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");

var updatedUserData = {};
updatedUserData["user/posts/location1"] = null;
updatedUserData["user/blogs/location2"] = null;
// Do a deep-path update
ref.update(updatedUserData).then(function() {
    //yay
}, function(error) {
    console.log("Error updating data:", error);
});

Transactions on the other hand are typically used for atomic data modifications where concurrent updates could cause an inconsistent data state. Imagine an upvote counter:

// user 1
upvotesRef.transaction(function (current_value) {
  return (current_value || 0) + 1;
});
// user 2
upvotesRef.transaction(function (current_value) {
  return (current_value || 0) + 1;
});

// upvotesRef will eventually be consistent with value += 2

Without transactions, you are not guaranteed this consistency:

// user 1
ref.on("value", function(snapshot) {
  console.log(snapshot.val()); // oops, could be the same value as user 2!
  ref.set(snapshot.val() + 1);
});
// user 2
ref.on("value", function(snapshot) {
  console.log(snapshot.val()); // oops, could be the same value as user 1!
  ref.set(snapshot.val() + 1);
});

More info here