[英]Javascript & JQuery: promises executing in unexpected order
我正在尝试从两个不同的函数中获取对象数组。 这些功能在数据库中执行一些查询。
我认为问题与事务的异步性质有关。
我尝试了几种方法来尝试使所有过程同步而没有成功。
我将详细介绍生成对象的代码片段:
预期的对象形状:
[
{
row:
{
prit_cd_item: 7,
prit_st_name: "1105 - Jazzboat"
},
tariffs:
[
{
cdPricing: 14,
dsPricing: "Operator tariff"
}
]
}
]
函数getTariffByProductItem:
getTariffByProductItem: function(productItemId) {
// Return Array of tariffs
var def = new $.Deferred();
var tariffs = [];
db.transaction(function(tx) {
tx.executeSql('select pric.pric_cd_pricing, pric.pric_ds_pricing ' +
'from tga_pricings pric ' +
'where date(\'now\') <= pric.pric_dt_valid_to ' +
'and date(\'now\') >= pric.pric_dt_valid_from ' +
'and pric.pric_cd_product_item = ?',
[productItemId],
function(tx,dbResult) {
if(dbResult.rows.length) {
for(var i = 0; i < dbResult.rows.length; i++) {
tariffs.push(
{
cdPricing: dbResult.rows.item(i).pric_cd_pricing,
dsPricing: dbResult.rows.item(i).pric_ds_pricing
}
);
}
def.resolve(tariffs);
}
});
}
, function(e) {
alert("There has been an error: " + e.message);
def.reject();
});
return def.promise();
}
函数editBookPaxBuyPrepare:
editBookPaxBuyPrepare: function(productId) {
var def = new $.Deferred();
var bookingId = $( '#edit-book-pax-pricing-form' ).data('bookid');
var paxId = $( '#edit-book-pax-pricing-form' ).data('paxid');
var productItems = [];
// Check for actual data
db.transaction(function(tx) {
// Get product items for product
tx.executeSql('select prit.prit_cd_item, prit.prit_st_name ' +
'from tga_products_catalog prod ' +
'inner join tga_product_items prit ' +
'on prit.prit_cd_product = prod.prod_cd_product ' +
'where prod.prod_cd_product = ?',
[ productId ],
function(tx, dbResult) {
if(dbResult.rows.length) {
// Set form action to EDIT
$('#edit-book-pax-buy-form').data('formaction', 'edit');
// Set product name label
$('#edit-book-pax-buy-product').text(dbResult.rows.item(0).prod_ds_product);
for(var i=0; i<dbResult.rows.length; i++) {
// For each producItem get tariffs
var dbRow = dbResult.rows.item(i);
var data = [];
$.when(bookings.getTariffByProductItem(dbRow.prit_cd_item))
.then(function(data) {
console.log("Product Item: " + dbRow.prit_st_name + " - tariffsArray: " + JSON.stringify(data));
productItems.push({ "row": dbRow, "tariffs": data });
});
}
def.resolve(productItems);
}
});
},
function(e) {
def.reject(e);
});
return def.promise();
}
调用上述两个函数的主要代码:
var listFieldset = $( '#edit-book-pax-buy-form-product-items-list' );
listFieldset.empty();
$.when(bookings.editBookPaxBuyPrepare(productId))
.done(function(productItems) {
console.log(JSON.stringify(productItems));
$( "#edit-book-pax-buy-product-item" ).tmpl( productItems ).appendTo( listFieldset );
listFieldset.trigger('create');
listFieldset.listview('refresh');
});
我得到的日志:
bookings.js:738 []
2014-11-23 20:03:06.151bookings.js:566 Product Item: 1105 - Local guide - tariffsArray: [{"cdPricing":7,"dsPricing":"Operator tariff"}]
2014-11-23 20:03:06.155bookings.js:566 Product Item: 1105 - Local guide - tariffsArray: [{"cdPricing":14,"dsPricing":"Operator tariff"}]
2014-11-23 20:03:06.159bookings.js:566 Product Item: 1105 - Local guide - tariffsArray: [{"cdPricing":15,"dsPricing":"Operator tariff"}]
2014-11-23 20:03:06.163bookings.js:566 Product Item: 1105 - Local guide - tariffsArray: [{"cdPricing":16,"dsPricing":"Operator tariff"}]
如您所见,“ console.log(JSON.stringify(productItems));” 在editBookPaxBuyPrepare函数内部循环中的console.log行之前执行。 预期的行为是相反的:等到editBookPaxBuyPrepare完成,然后在promise中记录returndes数组的内容。
我期望的是:
我需要一些好眼睛来帮助我。
欢迎任何帮助!
谢谢。
您的问题是代码的这一部分:
for(var i=0; i<dbResult.rows.length; i++) {
// For each producItem get tariffs
var dbRow = dbResult.rows.item(i);
var data = [];
$.when(bookings.getTariffByProductItem(dbRow.prit_cd_item))
.then(function(data) {
console.log("Product Item: " + dbRow.prit_st_name + " - tariffsArray: " + JSON.stringify(data));
productItems.push({ "row": dbRow, "tariffs": data });
});
}
def.resolve(productItems);
您调用def.resolve(productItems);
直接在循环之后但在循环内部,您有$.when(bookings.getTariffByProductItem(dbRow.prit_cd_item))
,它是异步的,不会阻塞循环,因此将在您调用def.resolve(productItems);
之后执行def.resolve(productItems);
另一个问题是,所有dbRow
.then()
回调的dbRow
都相同,因为这些回调是在循环完成之后执行的。
如果您计划在代码中以复杂的方式(包括循环)使用Promises,那么我建议您使用完整的 Promise库而不是jQuery。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.