Javascript 编写使用传递两个参数的回调的承诺
在最近的cordova应用程序中,我们使用了WebSQL api,因为它为我们提供了本地存储数据所需的设备支持和功能。我们将在一个即将到来的项目中再次使用它,所以我开始用它来探索承诺编辑添加了承诺实施的链接 以下是我目前掌握的情况:Javascript 编写使用传递两个参数的回调的承诺,javascript,promise,web-sql,babeljs,Javascript,Promise,Web Sql,Babeljs,在最近的cordova应用程序中,我们使用了WebSQL api,因为它为我们提供了本地存储数据所需的设备支持和功能。我们将在一个即将到来的项目中再次使用它,所以我开始用它来探索承诺编辑添加了承诺实施的链接 以下是我目前掌握的情况: function getConnection () { return window.openDatabase("cfa.db", "1.0", "CFA Database", 1000000); } function executeSql (transacti
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对象。然后,事务将正确启动,并返回承诺。但我尊重它只返回第一个参数。我该如何解决这个问题?在executeSql
方法中,您将resolve
传递给事务.executeSql
方法
承诺与普通值类似—您不能从函数返回多个值—就像您不能用多个值解析承诺一样。您可以选择使用[transaction,response]
数组(并使用babeljs的ES6解构赋值)或只使用一个参数进行解析。就你而言,很明显你只对回应感兴趣
function executeSQL(transaction, query, args){
return new Promise((resolve, reject) =>
transaction.executeSQL(query, args, (t,r) => resolve(r), reject);
);
}
请注意,您可以将数据源
类重构为:
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
}
}
您不需要在这里传递事务,因为您已经有了它,而且它为您解决的问题(上下文传递)并不存在于承诺中。因为您的目的是提供这两个值作为承诺结果的一部分,所以我建议将它们包装在一个对象中,以便接收它们的人可以提取它们:
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)
);
您能将该回调包装成一个返回一个合并结果的函数吗?您的意思是让事务和执行sql在一个承诺中完成吗?@agmcleod请确保使用最新版本和更新的core js,22小时前才有更多可调试的承诺:)无论哪种情况,如果你的应用程序在手机上运行,我强烈推荐bluebird支持core js。享受您没有内存限制的事实,选择更强大、更快、更可调试的实现。您可以告诉babel使用bluebird协程标志编译异步函数。实际上,我对这两个都感兴趣,因为如果需要的话,返回事务将使链接查询变得更容易。使用数组编辑示例非常简单。@agmcleod请确保使用数组解构语法-如果您愿意,我可以在答案中添加一个这样做的示例。再次感谢。鉴于ES7在编译器中是实验性的,它是否值得用于将交付给客户机的东西?尽管如此,我还是很喜欢它的简洁:)是的-你无论如何都在使用构建步骤,最好是充分利用itES6箭头函数,允许省略
{}
s和return
,如果它是一行,那么(tx)=>{return executeSQL(tx,query,args);}
实际上可以是tx=>executeSQL(tx,query,args)
。此外,您还可以在第二种情况下使用对象分解。@BenjaminGruenbaum,谢谢。我的解构正确吗?事实上,我从未接触过ES6。是的,在我看来不错,你可以分解更多级别,但公平地说,我不确定ES6是否允许这样做,或者只是巴贝尔。