小提琴:http://jsfiddle.net/smartdev101/eLxxpjp3/
在asyncAction函数调用中,已创建一个承诺,对两个异步操作getRecords
和getTotal
进行排序,然后在成功时调用onResult(data)
或onFail(info)
例外情况。
完成两个异步操作后如何进行onResult调用?
asyncAction: function(url, params, resultFunction, faultFunction) {
puremvc.asyncproxy.AsyncProxy.prototype.asyncAction.call(this, resultFunction, faultFunction);
if(!params.id) { //get master
var queryString = this.url.parse(url, true).query;
var offset = queryString.offset ? Number(queryString.offset) : 0;
var limit = queryString.limit ? Number(queryString.limit) : 20;
var data = {rows: null, total: null};
var self = this;
this.getRecords(data, offset, limit)
.then(function(data){return self.getTotal(data)})
//.fail(function(error){self.onFault(error)})
.done(function(data){self.onResult(data)})
} else { //get detail
this.getDetail(params.id);
}
},
getRecords: function(data, offset, limit) {
console.log('get records');
var defer = this.q.defer();
this.connection.query("SELECT title, name, company FROM speaker LIMIT ? OFFSET ?", [limit, offset], function(error, rows, fields){
console.log('get records done');
data.rows = rows;
defer.resolve(data);
//defer.reject("earlier");
});
return defer.promise;
},
getTotal: function(data) {
console.log('get total');
var defer = this.q.defer();
this.connection.query("SELECT * FROM speaker", function(error, rows, fields) { //SQL_CALC_FOUND_ROWS later
data.total = rows.length;
console.log('get total done');
defer.resolve(data);
//defer.reject("just like that");
});
return defer.promise;
},
onResult: function(data) {
console.log('on result');
puremvc.asyncproxy.AsyncProxy.prototype.onResult.call(this, data);
},
onFault: function(info) {
puremvc.asyncproxy.AsyncProxy.prototype.onFault.call(this, info);
}
答案 0 :(得分:0)
这篇文章帮了很多忙。 https://coderwall.com/p/ijy61g
编辑2-使用绑定作为建议的结果 - 问题是onResult
被调用而不管失败,所以我必须做if(data)
检查我不喜欢的,会有如果承诺具有某种最终.success
(.fail
)对应函数,那就太棒了。
编辑3 - 在当时链的末尾添加了this.onResult
,虽然它没有返回任何承诺,是否违反了任何规范?
编辑4 - 已宣传getConnection
getConnection: function() {
var defer = this.q.defer();
var mysql = require("mysql");
var pool = mysql.createPool({
host: common.Config.mySQLHost,
user: common.Config.mySQLUsername,
password: common.Config.mySQLPassword,
database: common.Config.mySQLDatabase
});
pool.getConnection(function(error, connection){
if(error) {
defer.reject(error)
} else {
defer.resolve(connection);
}
});
return defer.promise;
},
asyncAction: function(url, params, resultFunction, faultFunction) {
if(!params.id) { //get master
var queryString = this.url.parse(url, true).query;
var offset = queryString.offset ? Number(queryString.offset) : 0;
var limit = queryString.limit ? Number(queryString.limit) : 20;
var data = {rows: null, total: null};
var self = this;
this.getConnection()
.then(function(connection){return self.getRecords(data, offset, limit, connection)})
.then(function(value){return self.getTotal(value.data, value.connection)})
.then(function(value){self.onResult(value.data, value.connection)})
.fail(function(value){self.onFault(value.error, value.connection)})
} else { //get detail
this.getDetail(params.id);
}
},
getRecords: function(data, offset, limit, connection) {
var defer = this.q.defer();
connection.query("SELECT title, name, company FROM speaker LIMIT ? OFFSET ?", [limit, offset], function(error, rows, fields){
if(error) {
defer.reject({error:error, connection:connection});
} else {
data.rows = rows;
defer.resolve({data: data, connection:connection});
}
});
return defer.promise;
},
getTotal: function(data, connection) {
var defer = this.q.defer();
connection.query("SELECT count(*) AS total FROM speaker", function(error, rows, fields) {
if(error) {
defer.reject({error:error, connection:connection});
} else {
data.total = rows[0].total;
defer.resolve({connection:connection, data:data});
}
});
return defer.promise;
},
onResult: function(data, connection) {
console.log(data);
connection.release();
},
onFault: function(info, connection) {
console.log(info)
connection.release();
}
答案 1 :(得分:0)
似乎可以简化这一点。您似乎只希望同步执行这些异步操作。如果您退回承诺,链中的原始承诺将成为新承诺。最终的失败将抓住第一个被拒绝的承诺。
asyncAction: function(url, params, resultFunction, faultFunction) {
puremvc.asyncproxy.AsyncProxy.prototype.asyncAction.call(this, resultFunction, faultFunction);
if(!params.id) { //get master
var queryString = this.url.parse(url, true).query;
var offset = queryString.offset ? Number(queryString.offset) : 0;
var limit = queryString.limit ? Number(queryString.limit) : 20;
var data = {rows: null, total: null};
var self = this;
this.getRecords(data, offset, limit)
.then(function(data) {
return self.getTotal(data);
})
.then(this.onResult.bind(this))
.fail(this.onFault);
} else { //get detail
this.getDetail(params.id);
}
},
getRecords: function(data, offset, limit) {
console.log('get records');
var defer = this.q.defer();
this.connection.query("SELECT title, name, company FROM speaker LIMIT ? OFFSET ?", [limit, offset], function(error, rows, fields){
console.log('get records done');
data.rows = rows;
defer.resolve(data);
//defer.reject("earlier");
});
return defer.promise;
},
getTotal: function(data) {
console.log('get total');
var defer = this.q.defer();
this.connection.query("SELECT * FROM speaker", function(error, rows, fields) { //SQL_CALC_FOUND_ROWS later
data.total = rows.length;
console.log('get total done');
defer.resolve(data);
//defer.reject("just like that");
});
return defer.promise;
},
onResult: function(data) {
console.log('on result');
puremvc.asyncproxy.AsyncProxy.prototype.onResult.call(this, data);
},
答案 2 :(得分:0)
User2727195,这是我的完整版本,基于您自己的答案中发布的原始未经编辑的代码。
没有改进逻辑/流程的方法,只是为了改善语法。因此,它与你当时的答案一样好。为了使一切正常运行,您需要应用自己以后提出的想法和其他建议。
因此,这不是一个独立的答案,不应该被选中。如果它开始吸引负面投票,那么我会删除它,以便尽可能拖拽想法。
asyncAction: function(url, params) {
if(!params.id) { //get master
var queryString = this.url.parse(url, true).query;
this.getRecords({}, Number(queryString.offset || 0), Number(queryString.limit || 20))
.then(this.getTotal.bind(this))
.fail(this.onFault.bind(this))
.done(this.onResult.bind(this));
} else { //get detail
this.getDetail(params.id);
}
},
connectionQueryPromisifier = function() {
// This is a promisifying adaptor for connection.query .
// In your own version, you will probably choose to rewrite connection.query rather than use an adapter.
var args = Array.prototype.slice.call(arguments).concat(function(error, rows, fields) {
if(error) { defer.reject(error); }
else { defer.resolve({ rows:rows, fields:fields }); }
}),
defer = this.q.defer();
this.connection.query.apply(this, args);
return defer.promise;
},
getRecords: function(data, offset, limit) {
//Here, you take advantage of having promisified connection.query .
return this.connectionQueryPromisifier("SELECT title, name, company FROM speaker LIMIT ? OFFSET ?", [limit, offset]).then(function(obj) {
data.rows = obj.rows;
});
},
getTotal: function(data) {
//Here, you take advantage of having promisified connection.query .
return this.connectionQueryPromisifier("SELECT * FROM speaker").then(function(obj) {
data.total = obj.rows.length;
});
},
onResult: function(data) {
console.log('on result');
},
onFault: function(info) {
console.log('onFault');
}