编写一个使用传递两个参数的回调的承诺

时间:2015-02-20 20:13:11

标签: javascript promise web-sql babeljs

在最近的一个cordova应用程序中,我们使用了WebSQL api,因为它为我们提供了在本地存储数据所需的设备支持和功能。我们将再次使用它来进行即将开展的项目,因此我开始使用implemented in core.js, using BabelJS探索promises。 编辑添加了对promises实施的链接。

这是我到目前为止所拥有的:

function getConnection () {
  return window.openDatabase("cfa.db", "1.0", "CFA Database", 1000000);
}

function executeSql (transaction, query, args) {
  return new Promise((resolve, reject) => {
    console.log(query);
    transaction.executeSql(query, args, resolve, reject);
  });
}

function transaction (connection) {
  return new Promise((resolve, reject) => {
    connection.transaction(resolve, reject);
  });
}

class DataSource {
  executeSql (query, args) {
    var connection = getConnection();
    transaction(connection).then((tx) => {
      return executeSql(tx, query, args);
    }).then((tx, res) => {
      console.log(tx, res.rows.length);
    }, (tx, e) => {
      console.log(e);
    });
  }
}

以下是使用api进行简单查询的准系统:

var connection = getConnection();
connection.transaction(function (tx, res) {
  tx.executeSql("SELECT * FROM table", [], function (tx, res) {
    console.log(res.rows.length);
  }, function (tx, err) {
    console.log(err);
  });
}, function (err) {
  console.log(err);
});

因此事务只是传递事务实例,我可以使用它来执行sql语句。这很简单,可以包含一个承诺。更棘手的部分是executeSql方法的回调。它传递了事务,很适合用于其他查询。然后它传递结果数据。我如何将其包含在承诺中?

在我的DataSource类中,executeSql方法记录了一个事务对象,但没有res对象。然后事务正确触发,返回promise即可。但我尊重它只返回第一个参数。我怎么能绕过这个?

2 个答案:

答案 0 :(得分:2)

executeSql方法中,您将resolve传递给transaction.executeSQL方法。

Promise与普通值一样 - 您无法从函数返回多个值 - 就像您无法解决具有多个值的promise一样。您可以选择使用[transaction, response]数组解析它(并使用babeljs的ES6解构分配),或者只使用一个参数进行解析。在您的情况下,您很清楚您只对响应感兴趣。

function executeSQL(transaction, query, args){
    return new Promise((resolve, reject) =>
        transaction.executeSQL(query, args, (t,r) => resolve(r), reject);
    );
}

请注意,您可以将DataSource课程重构为:

class DataSource{
    async executeSQL(query, args){
        let connection = getConnection();
        let transaction = await transaction(connection);
        let result = await executeSQL(transaction, query, args);
        return result; // or console.log result.rows.length
    }
}

你不需要在这里传递交易,因为你已经拥有它并且它解决的问题(上下文传递)并不存在于promises中。

答案 1 :(得分:1)

由于您的意图是将两个值都作为承诺结果的一部分提供,我建议将它们包装在一个对象中,以便任何接收它的人都可以提取它们:

function executeSql (transaction, query, args) {
    return new Promise((resolve, reject) => {
        console.log(query);
        transaction.executeSql(query, args, (t, r) => resolve({ 
            transaction: t, 
            result: r
        }), reject);
    });
}

用法:

transaction(connection)
.then(tx => executeSql(tx, query, args))
.then({result} => console.log(tx, result.rows.length), 
      e => console.log(e)
);