Javascript 使用Node.js将值从承诺传递到承诺
我正在尝试传递一个我使用firebase一块一块地构建的对象。如果有更好的方法一步一步地构造对象,我并不需要沿着承诺链传递对象。这是我的密码:Javascript 使用Node.js将值从承诺传递到承诺,javascript,node.js,promise,firebase-realtime-database,Javascript,Node.js,Promise,Firebase Realtime Database,我正在尝试传递一个我使用firebase一块一块地构建的对象。如果有更好的方法一步一步地构造对象,我并不需要沿着承诺链传递对象。这是我的密码: var queue = new Queue(productUpdateQueue, function(data, progress, resolve, reject) { var incomingUpdateData = data; var receiptID = incomingUpdateData.receiptID;
var queue = new Queue(productUpdateQueue, function(data, progress, resolve, reject) {
var incomingUpdateData = data;
var receiptID = incomingUpdateData.receiptID;
var userID = incomingUpdateData.userID;
var oldProductID = incomingUpdateData.oldProductID;
var newProductID = incomingUpdateData.newProductID;
var newReceipt = incomingUpdateData.newReceipt;
var postID = "";
var updateObject = {};
updateObject['usersPrivate/'+userID+'/receipts/'+receiptID+'/items/'+oldProductID] = null;
updateObject['usersPrivate/'+userID+'/receipts/'+receiptID+'/items/'+newProductID] = newReceipt;
clicks.child('VigLink').orderByChild('item').equalTo(oldProductID).once('value', function(cuidSnapshot) {
return cuidSnapshot.forEach(function(cuidSnapshot) {
var cuid = cuidSnapshot.key;
updateObject['clicks/VigLink/'+cuid+'/item'] = newProductID;
console.log('one');
progress(20);
});
}).then(function() {
return userReceiptMetrics.child(userID).child('receipts').child(receiptID).child('items').child(oldProductID).once('value', function(oldSnapshot) {
var data = oldSnapshot.val()
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/items/'+oldProductID] = null
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/items/'+newProductID] = data
if (data != null) {
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/itemIDs/'+newProductID] = now
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/itemIDs/'+oldProductID] = null
};
console.log('two');
progress(40);
});
}).then(function() {
return userReceiptMetrics.child(userID).child('shops').child(oldProductID).once('value', function(oldSnapshot) {
var data = oldSnapshot.val()
updateObject['userReceiptMetrics/'+userID+'/shops/'+oldProductID] = null;
updateObject['userReceiptMetrics/'+userID+'/shops/'+newProductID] = data;
if (data != null) {
updateObject['userReceiptMetrics/'+userID+'/shopIDs/'+newProductID] = now;
updateObject['userReceiptMetrics/'+userID+'/shopIDs/'+oldProductID] = null;
};
console.log('three');
progress(60);
});
}).then(function() {
return posts.once('value', function(postSnapshot) {
// use Promise.all and Array#map to wait for all these queries to finish
var allPosts = postSnapshot.val()
var postKeys = Object.keys(allPosts)
return Promise.all(postKeys.map(function(postKey) {
var postID = postKey;
return posts.child(postID).child('items').child(oldProductID).once('value', function(itemSnapshot) {
itemSnapshot.forEach(function(itemSnapshot) {
var itemData = itemSnapshot.val()
console.log('post snapshot'+ itemSnapshot);
updateObject['posts/'+postID+'/items/'+oldProductID] = null
updateObject['posts/'+postID+'/items/'+newProductID] = itemData
});
});
})).then(function(results) {
// put progress update in .then, and return the results
progress(75);
return results;
});
});
}).then(function() {
// Move to next item
return console.log('hey look here'+updateObject['posts/'+postID+'/items/'+newProductID]);
return firebaseRoot.update(updateObject, function(error) {
if (error) {
console.log("Error updating data:", error);
reject()
} else {
progress(100);
// resolve();
console.log('four');
}
});
});
// Finish the task asynchronously
setTimeout(function() {
reject();
}, 10000);
});
输出为:
one
two
three
hey look hereundefined
post snapshot[object Object]
post snapshot[object Object]
post snapshot[object Object]
post snapshot[object Object]
post snapshot[object Object]
post snapshot[object Object]
post snapshot[object Object]
post snapshot[object Object]
非常感谢您的任何帮助。您需要更改您的。然后从(现在问题中已更改,但代码最初有此功能) 到 因此,您的代码总是更新在
新队列
回调中声明的updateObject
此外,每行中的第一行需要添加一个返回
因此,与其
userReceiptMetrics.child(userID).child('receipts').child(receiptID).child('items').child(oldProductID).once('value', function(oldSnapshot) {
你有
return userReceiptMetrics.child(userID).child('receipts').child(receiptID).child('items').child(oldProductID).once('value', function(oldSnapshot) {
进度调用需要放在.once回调的末尾
总之,代码应该看起来像(删除了大部分正确的代码,希望这是可以理解的)
var queue = new Queue(productUpdateQueue, function(data, progress, resolve, reject) {
// removed for brevity
var updateObject = {};
// removed for brevity
clicks.child('VigLink').orderByChild('item').equalTo(oldProductID).once('value', function(cuidSnapshot) {
// removed for brevity
progress(12);
}).then(function() {
return userReceiptMetrics.child(userID).child('receipts').child(receiptID).child('items').child(oldProductID).once('value', function(oldSnapshot) {
// removed for brevity
progress(25);
});
}).then(function() {
return userReceiptMetrics.child(userID).child('shops').child(oldProductID).once('value', function(oldSnapshot) {
// removed for brevity
progress(50);
});
}).then(function() {
return posts.orderByChild('items').equalTo(oldProductID).once('value', function(postSnapshot) {
// use Promise.all and Array#map to wait for all these queries to finish
return Promise.all(postSnapshot.map(function(postSnapshot) {
var postID = postSnapshot.key;
return posts.child(postID).child('items').child(oldProductID).once('value', function(itemSnapshot) {
itemSnapshot.forEach(function(itemSnapshot) {
var itemData = itemSnapshot.val()
updateObject['posts/'+postID+'/items/'+oldProductID] = null
updateObject['posts/'+postID+'/items/'+newProductID] = itemData
});
});
})).then(function(results) {
// put progress update in .then, and return the results
progress(75);
return results;
});
});
}).then(function() {
// Move to next item
console.log(updateObject);
// removed for brevity
});
// Finish the task asynchronously
setTimeout(function() {
reject();
}, 10000);
});
所以我终于想出了方法。我在一步一步地传递对象时遇到了一个问题,但我真正想做的是一步一步地创建对象。所以我在承诺链之外创建了对象,并一步一步地构建它。这里的主要障碍之一是完成循环,然后继续下一个promis为此,我使用
Promise.all()
返回结果
它是有效的,现在我对承诺的作用有了更多的了解。如果这能帮助你,请接受:
var queue = new Queue(productUpdateQueue, function(data, progress, resolve, reject) {
var incomingUpdateData = data;
var receiptID = incomingUpdateData.receiptID;
var userID = incomingUpdateData.userID;
var oldProductID = incomingUpdateData.oldProductID;
var newProductID = incomingUpdateData.newProductID;
var newReceipt = incomingUpdateData.newReceipt;
var postID = "-KZOO0UII67uOmYo6DJh";
var postKeys = [];
var updateObject = {};
updateObject['usersPrivate/'+userID+'/receipts/'+receiptID+'/items/'+oldProductID] = null;
updateObject['usersPrivate/'+userID+'/receipts/'+receiptID+'/items/'+newProductID] = newReceipt;
return clicks.child('VigLink').orderByChild('item').equalTo(oldProductID).once('value', function(cuidSnapshot) {
return cuidSnapshot.forEach(function(cuidSnapshot) {
var cuid = cuidSnapshot.key;
updateObject['clicks/VigLink/'+cuid+'/item'] = newProductID;
progress(10);
});
}).then(function() {
return userReceiptMetrics.child(userID).child('receipts').child(receiptID).child('items').child(oldProductID).once('value', function(oldSnapshot) {
var data = oldSnapshot.val()
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/items/'+oldProductID] = null
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/items/'+newProductID] = data
if (data != null) {
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/itemIDs/'+newProductID] = now
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/itemIDs/'+oldProductID] = null
};
progress(25);
});
}).then(function() {
return userReceiptMetrics.child(userID).child('shops').child(oldProductID).once('value', function(oldSnapshot) {
var data = oldSnapshot.val()
updateObject['userReceiptMetrics/'+userID+'/shops/'+oldProductID] = null;
updateObject['userReceiptMetrics/'+userID+'/shops/'+newProductID] = data;
if (data != null) {
updateObject['userReceiptMetrics/'+userID+'/shopIDs/'+newProductID] = now;
updateObject['userReceiptMetrics/'+userID+'/shopIDs/'+oldProductID] = null;
};
progress(40);
});
}).then(function() {
progress(55);
return posts.orderByChild('receipt').equalTo(receiptID).once('value');
}).then(function(postSnapshot) {
return postSnapshot.forEach(function(post) {
progress(70);
postKeys.push(post.key)
});
}).then(function() {
return Promise.all(postKeys.map(function(postKey) {
return posts.child(postKey).child('items').child(oldProductID).once('value', function(itemSnapshot) {
var itemData = itemSnapshot.val()
updateObject['posts/'+postKey+'/items/'+oldProductID] = null;
updateObject['posts/'+postKey+'/items/'+newProductID] = itemData;
});
})).then(function(results) {
progress(85);
return results;
});
}).then(function() {
return firebaseRoot.update(updateObject, function(error) {
if (error) {
console.log("Error updating data:", error);
reject()
} else {
progress(100);
resolve();
}
});
});
// Finish the task asynchronously
setTimeout(function() {
reject();
}, 10000);
});
您是否可以检查执行是否实际进入为userReceiptMetrics.child(userID).child('receipts').child(receiptID.).child('items').child(oldProductID)上的值事件注册的回调变量?正如我现在看到的,它永远不会退出第一个承诺部分。我看到进度设置为12,然后服务器崩溃。那么,是什么让你说它永远不会退出第一个承诺呢?报告的错误似乎指向试图影响updateObject['userReceiptMetrics/'+userID+'/shops/'+oldProductID]的指令是的,这是我没有得到的。如果我把console.log()语句放在第一个承诺之外的任何地方,它就不会被调用。此外,我正在看着它在运行时(在崩溃之前)将数据放在我的firebase上而且它似乎只是在崩溃前将进度设置为12的部分。真的,我想可能
return updateObject;
不会将对象传递给下一个承诺,因此updateObject
是未定义的。我错了吗?感谢十亿Jaromanda X!!我很确定他们的承诺是按顺序发生的在我将对象设置到Firebase之前,我做了一些其他错误。你的帮助非常有用,正因为如此,我在本周六授予你“g”奖。你是正式的g.Ok。因此,看起来除了一个问题外,这一切都正常。我使用的两个循环都在整个承诺链结束后完成。你不能使用吗承诺中的循环?抱歉,没有注意到forEach循环也使用异步代码-让我修改我编辑的答案(希望如此)对于在forEach内部使用asynch的部分,正确的代码-它使用Promise.all和Array#map来等待所有内部查询的解析它告诉我,.map不是一个函数
var queue = new Queue(productUpdateQueue, function(data, progress, resolve, reject) {
// removed for brevity
var updateObject = {};
// removed for brevity
clicks.child('VigLink').orderByChild('item').equalTo(oldProductID).once('value', function(cuidSnapshot) {
// removed for brevity
progress(12);
}).then(function() {
return userReceiptMetrics.child(userID).child('receipts').child(receiptID).child('items').child(oldProductID).once('value', function(oldSnapshot) {
// removed for brevity
progress(25);
});
}).then(function() {
return userReceiptMetrics.child(userID).child('shops').child(oldProductID).once('value', function(oldSnapshot) {
// removed for brevity
progress(50);
});
}).then(function() {
return posts.orderByChild('items').equalTo(oldProductID).once('value', function(postSnapshot) {
// use Promise.all and Array#map to wait for all these queries to finish
return Promise.all(postSnapshot.map(function(postSnapshot) {
var postID = postSnapshot.key;
return posts.child(postID).child('items').child(oldProductID).once('value', function(itemSnapshot) {
itemSnapshot.forEach(function(itemSnapshot) {
var itemData = itemSnapshot.val()
updateObject['posts/'+postID+'/items/'+oldProductID] = null
updateObject['posts/'+postID+'/items/'+newProductID] = itemData
});
});
})).then(function(results) {
// put progress update in .then, and return the results
progress(75);
return results;
});
});
}).then(function() {
// Move to next item
console.log(updateObject);
// removed for brevity
});
// Finish the task asynchronously
setTimeout(function() {
reject();
}, 10000);
});
var queue = new Queue(productUpdateQueue, function(data, progress, resolve, reject) {
var incomingUpdateData = data;
var receiptID = incomingUpdateData.receiptID;
var userID = incomingUpdateData.userID;
var oldProductID = incomingUpdateData.oldProductID;
var newProductID = incomingUpdateData.newProductID;
var newReceipt = incomingUpdateData.newReceipt;
var postID = "-KZOO0UII67uOmYo6DJh";
var postKeys = [];
var updateObject = {};
updateObject['usersPrivate/'+userID+'/receipts/'+receiptID+'/items/'+oldProductID] = null;
updateObject['usersPrivate/'+userID+'/receipts/'+receiptID+'/items/'+newProductID] = newReceipt;
return clicks.child('VigLink').orderByChild('item').equalTo(oldProductID).once('value', function(cuidSnapshot) {
return cuidSnapshot.forEach(function(cuidSnapshot) {
var cuid = cuidSnapshot.key;
updateObject['clicks/VigLink/'+cuid+'/item'] = newProductID;
progress(10);
});
}).then(function() {
return userReceiptMetrics.child(userID).child('receipts').child(receiptID).child('items').child(oldProductID).once('value', function(oldSnapshot) {
var data = oldSnapshot.val()
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/items/'+oldProductID] = null
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/items/'+newProductID] = data
if (data != null) {
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/itemIDs/'+newProductID] = now
updateObject['userReceiptMetrics/'+userID+'/receipts/'+receiptID+'/itemIDs/'+oldProductID] = null
};
progress(25);
});
}).then(function() {
return userReceiptMetrics.child(userID).child('shops').child(oldProductID).once('value', function(oldSnapshot) {
var data = oldSnapshot.val()
updateObject['userReceiptMetrics/'+userID+'/shops/'+oldProductID] = null;
updateObject['userReceiptMetrics/'+userID+'/shops/'+newProductID] = data;
if (data != null) {
updateObject['userReceiptMetrics/'+userID+'/shopIDs/'+newProductID] = now;
updateObject['userReceiptMetrics/'+userID+'/shopIDs/'+oldProductID] = null;
};
progress(40);
});
}).then(function() {
progress(55);
return posts.orderByChild('receipt').equalTo(receiptID).once('value');
}).then(function(postSnapshot) {
return postSnapshot.forEach(function(post) {
progress(70);
postKeys.push(post.key)
});
}).then(function() {
return Promise.all(postKeys.map(function(postKey) {
return posts.child(postKey).child('items').child(oldProductID).once('value', function(itemSnapshot) {
var itemData = itemSnapshot.val()
updateObject['posts/'+postKey+'/items/'+oldProductID] = null;
updateObject['posts/'+postKey+'/items/'+newProductID] = itemData;
});
})).then(function(results) {
progress(85);
return results;
});
}).then(function() {
return firebaseRoot.update(updateObject, function(error) {
if (error) {
console.log("Error updating data:", error);
reject()
} else {
progress(100);
resolve();
}
});
});
// Finish the task asynchronously
setTimeout(function() {
reject();
}, 10000);
});