简体   繁体   中英

Meteor._wrapAsync

I wrapped a function writeTransaction() with Meteor._wrapAsync and called it 5 times in a for loop which writes a MySQL transaction.

However from the MySQL query logs, it seems that the next iteration of the loop is executed before the function writeTransactionSync() in the previous loop has finished.

If Meteor._wrapAsync does not make the function blocking, how can we make the function synchronous?

Server-side Code

writeTransaction = function(data, callback) {

    var mysql = Meteor.require('mysql')
    var connection = mysql.createConnection(info).connect()


    connection.beginTransaction(Meteor.bindEnvironment(function(err) {
        connection.query('DELETE FROM orders WHERE _id = ?', [data._id], Meteor.bindEnvironment( function(err) {
            connection.commit( Meteor.bindEnvironment( function(err) {

            }))
        }))
    }))

    callback(null)

}


writeTransactionSync = Meteor._wrapAsync(writeTransaction)

for(var i=0; i<5; i++) {
    writeTransactionSync(data[i])
}

MySQL Query Log

  329 Connect   root@localhost on meteor
  330 Connect   root@localhost on meteor
  331 Connect   root@localhost on meteor
  332 Connect   root@localhost on meteor
  333 Connect   root@localhost on meteor
  329 Query START TRANSACTION
  330 Query START TRANSACTION
  331 Query START TRANSACTION
  332 Query START TRANSACTION
  333 Query START TRANSACTION
  329 Query DELETE FROM orders WHERE _id = '34zCYZXBxEkJapkYh'
  330 Query DELETE FROM orders WHERE _id = 'SNR8zTEzGCw6X7RZ2'
  331 Query DELETE FROM orders WHERE _id = 'TAF2TJkN5LzFRqAnX'
  332 Query DELETE FROM orders WHERE _id = '57pJbvFYmHTpM5E6a'
  333 Query DELETE FROM orders WHERE _id = 'BtNLGa3gjRGAfmMFf'
  331 Query COMMIT
  332 Query COMMIT
  329 Query COMMIT
  330 Query COMMIT
  333 Query COMMIT

Meteor._wrapAsync is synchronous, provided that you fire the callback after all the tasks are done. It will only block the fiber if it knows the method has completed, so when you call callback(null) , it assumes it is complete.

You have used callback(null) after you call connection.query but it would be called regardless of whether your query has completed or not, and since it takes a bit of time for a query to execute with MySQL, its likely its always complete (and act asynchronous) before the query has actually run.

You should place it inside the callback of the query:

connection.beginTransaction(function(err) {
    connection.query('DELETE FROM orders WHERE _id = ?', [data._id], function(err) {
        connection.commit(function(err) {
            callback(null);
        });
    });
});

Also you don't need Meteor.bindEnvironment when you use Meteor._wrapAsync , especially when you're not using any Meteor code in the functions anywhere (You dont use meteor code in any of your connection callbacks, so its not needed).

You can checkout this video on Meteor._wrapAsync here in eventedmind . It did a good job on this topic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM