js promises 的问题(bluebird)
Trouble with js promises (bluebird)
我正在尝试从列表中的 MailChimp 中创建合并字段(如果它们尚不存在)。如果它们不存在,我希望将它们推送到承诺列表中,我在其中使用 promises.all
来确保已添加所有必要的列表项。
虽然这不起作用。我究竟做错了什么?
var productDict = []
var getMergeNumPromise = new Promise(
function(resolve, reject) {
// call to mailchimp to get the number of merge fields
rp({
uri: MAILCHIMP_MERGEFIELDS_URI,
qs:{count:1},
json:true,
headers:MAILCHIMP_HEADER
})
.then(function( mergeFieldList ) {
console.log("total items: " + mergeFieldList.total_items)
resolve(mergeFieldList.total_items)
})
.catch(function(err) {
console.log("error getting merge field count: " + err)
reject(err)
})
}
)
var getMergeFieldsPromise = new Promise(
function( resolve, reject ) {
getMergeNumPromise.then(function( total, err ){
//gets just the name and tag for all merge fields in the list
rp({
uri: MAILCHIMP_MERGEFIELDS_URI,
qs:{
count: total,
fields: "merge_fields.tag,merge_fields.name"
},
headers: MAILCHIMP_HEADER
})
.then(function( fullFieldList ) {
console.log("FULL FIELD BODY" + fullFieldList)
var body = JSON.parse(fullFieldList)
resolve(body.merge_fields)
})
.catch(function(err){
console.log("error getting fields: " + err)
reject(err)
})
})
}
)
function addMergeField (prodName , dictPos) {
return new Promise (
function(resolve, reject) {
fieldBody = { name : prodName , type : "number"}
//post request to make the new merge field
rp({
method: "POST",
uri: MAILCHIMP_MERGEFIELDS_URI,
json: true,
headers: MAILCHIMP_HEADER,
body: fieldBody
})
.then(function(body) {
//update product dictionary
productDict[dictPos] = {tag : body.tag, name : body.name}
console.log("MERGE FIELD RESPONSE " + JSON.stringify(body))
resolve(body)
})
.catch(function(err) {
console.log("error creating merge field for product id: " + err)
reject(err)
})
}
)
}
var updateMergeFields = getMergeFieldsPromise.then(
function( mergeFieldList ) {
// resolved ids keeps track of ids that have already been added
var resolvedIDS = {}
//holds result of find to look for product ids
var foundMCMatch
// holds productIDS[i]
var product
//console.log("merge field list" + JSON.stringify(mergeFieldList))
for(var i = 0; i < productIDS.length; i++) {
console.log("checking if product id " + productIDS[i] + "exists")
product = productIDS[i]
// tries to find a match to see if fields are already in mailchimp
foundMCMATCH = mergeFieldList.find(x => x.name == product)
if(foundMCMATCH) {
console.log("foundMCMATCH" + JSON.stringify(foundMCMATCH))
//updates product dict with matching tag/name from mailchimp
productDict[i] = {
tag : foundMCMATCH.tag,
name : foundMCMATCH.name
}
//console.log("PRODUCT DICT " + JSON.stringify(productDict))
}
//if field isn't on mailchimp
else if (!resolvedIDS[product])
{
resolvedIDS[product] = true
// adds product id as merge field becasue it doesn't exist
allProductIDPromises.push(
addMergeField(product,i)
)
}
}
}
)
allProductIDPromises.push( getMergeFieldsPromise, getMergeNumPromise, updateMergeFields )
Promise.all(allProductIDPromises)
.then(function() {
//function here that's running out of order
}
注意:我正在使用请求承诺来发出我的 post 请求,因此它们已经被承诺。
getMergeFieldsPromise
的 then
回调没有 returning 任何东西,所以一旦 getMergeFieldsPromise
被解决,它就不会等待 addMergeField
承诺,而是立即解决(undefined
作为承诺值)。
要解决这个问题,请在 then
回调中将 allProductIDPromises
设为局部变量并对其调用 Promise.all
,然后 return 在那里:
var updateMergeFields = getMergeFieldsPromise.then(
function( mergeFieldList ) {
// **** make the array of promises local to this function
var allProductIDPromises = [];
// resolved ids keeps track of ids that have already been added
var resolvedIDS = {}
//holds result of find to look for product ids
var foundMCMatch
// holds productIDS[i]
var product
//console.log("merge field list" + JSON.stringify(mergeFieldList))
for(var i = 0; i < productIDS.length; i++) {
console.log("checking if product id " + productIDS[i] + "exists")
product = productIDS[i]
// tries to find a match to see if fields are already in mailchimp
foundMCMATCH = mergeFieldList.find(x => x.name == product)
if(foundMCMATCH) {
console.log("foundMCMATCH" + JSON.stringify(foundMCMATCH))
//updates product dict with matching tag/name from mailchimp
productDict[i] = {
tag : foundMCMATCH.tag,
name : foundMCMATCH.name
}
//console.log("PRODUCT DICT " + JSON.stringify(productDict))
}
//if field isn't on mailchimp
else if (!resolvedIDS[product])
{
resolvedIDS[product] = true
// adds product id as merge field becasue it doesn't exist
allProductIDPromises.push(
addMergeField(product,i)
)
}
}
// **** call Promise.all here, and return it
return Promise.all(allProductIDPromises);
}
)
然后,你应该删除这个:
allProductIDPromises.push( ... )
...并且由于您的主要三个承诺已经与 then
链接在一起,您只需要对最后一个承诺执行 then
:
updateMergeFields.then(function(addedMergeFields) {
// ... all is ready now.
}
最后,阅读您多次使用的 Promise constructor anti-pattern:您不应该使用 new Promise
,而实际上您可以 return 承诺(例如 return rp()
).
我正在尝试从列表中的 MailChimp 中创建合并字段(如果它们尚不存在)。如果它们不存在,我希望将它们推送到承诺列表中,我在其中使用 promises.all
来确保已添加所有必要的列表项。
虽然这不起作用。我究竟做错了什么?
var productDict = []
var getMergeNumPromise = new Promise(
function(resolve, reject) {
// call to mailchimp to get the number of merge fields
rp({
uri: MAILCHIMP_MERGEFIELDS_URI,
qs:{count:1},
json:true,
headers:MAILCHIMP_HEADER
})
.then(function( mergeFieldList ) {
console.log("total items: " + mergeFieldList.total_items)
resolve(mergeFieldList.total_items)
})
.catch(function(err) {
console.log("error getting merge field count: " + err)
reject(err)
})
}
)
var getMergeFieldsPromise = new Promise(
function( resolve, reject ) {
getMergeNumPromise.then(function( total, err ){
//gets just the name and tag for all merge fields in the list
rp({
uri: MAILCHIMP_MERGEFIELDS_URI,
qs:{
count: total,
fields: "merge_fields.tag,merge_fields.name"
},
headers: MAILCHIMP_HEADER
})
.then(function( fullFieldList ) {
console.log("FULL FIELD BODY" + fullFieldList)
var body = JSON.parse(fullFieldList)
resolve(body.merge_fields)
})
.catch(function(err){
console.log("error getting fields: " + err)
reject(err)
})
})
}
)
function addMergeField (prodName , dictPos) {
return new Promise (
function(resolve, reject) {
fieldBody = { name : prodName , type : "number"}
//post request to make the new merge field
rp({
method: "POST",
uri: MAILCHIMP_MERGEFIELDS_URI,
json: true,
headers: MAILCHIMP_HEADER,
body: fieldBody
})
.then(function(body) {
//update product dictionary
productDict[dictPos] = {tag : body.tag, name : body.name}
console.log("MERGE FIELD RESPONSE " + JSON.stringify(body))
resolve(body)
})
.catch(function(err) {
console.log("error creating merge field for product id: " + err)
reject(err)
})
}
)
}
var updateMergeFields = getMergeFieldsPromise.then(
function( mergeFieldList ) {
// resolved ids keeps track of ids that have already been added
var resolvedIDS = {}
//holds result of find to look for product ids
var foundMCMatch
// holds productIDS[i]
var product
//console.log("merge field list" + JSON.stringify(mergeFieldList))
for(var i = 0; i < productIDS.length; i++) {
console.log("checking if product id " + productIDS[i] + "exists")
product = productIDS[i]
// tries to find a match to see if fields are already in mailchimp
foundMCMATCH = mergeFieldList.find(x => x.name == product)
if(foundMCMATCH) {
console.log("foundMCMATCH" + JSON.stringify(foundMCMATCH))
//updates product dict with matching tag/name from mailchimp
productDict[i] = {
tag : foundMCMATCH.tag,
name : foundMCMATCH.name
}
//console.log("PRODUCT DICT " + JSON.stringify(productDict))
}
//if field isn't on mailchimp
else if (!resolvedIDS[product])
{
resolvedIDS[product] = true
// adds product id as merge field becasue it doesn't exist
allProductIDPromises.push(
addMergeField(product,i)
)
}
}
}
)
allProductIDPromises.push( getMergeFieldsPromise, getMergeNumPromise, updateMergeFields )
Promise.all(allProductIDPromises)
.then(function() {
//function here that's running out of order
}
注意:我正在使用请求承诺来发出我的 post 请求,因此它们已经被承诺。
getMergeFieldsPromise
的 then
回调没有 returning 任何东西,所以一旦 getMergeFieldsPromise
被解决,它就不会等待 addMergeField
承诺,而是立即解决(undefined
作为承诺值)。
要解决这个问题,请在 then
回调中将 allProductIDPromises
设为局部变量并对其调用 Promise.all
,然后 return 在那里:
var updateMergeFields = getMergeFieldsPromise.then(
function( mergeFieldList ) {
// **** make the array of promises local to this function
var allProductIDPromises = [];
// resolved ids keeps track of ids that have already been added
var resolvedIDS = {}
//holds result of find to look for product ids
var foundMCMatch
// holds productIDS[i]
var product
//console.log("merge field list" + JSON.stringify(mergeFieldList))
for(var i = 0; i < productIDS.length; i++) {
console.log("checking if product id " + productIDS[i] + "exists")
product = productIDS[i]
// tries to find a match to see if fields are already in mailchimp
foundMCMATCH = mergeFieldList.find(x => x.name == product)
if(foundMCMATCH) {
console.log("foundMCMATCH" + JSON.stringify(foundMCMATCH))
//updates product dict with matching tag/name from mailchimp
productDict[i] = {
tag : foundMCMATCH.tag,
name : foundMCMATCH.name
}
//console.log("PRODUCT DICT " + JSON.stringify(productDict))
}
//if field isn't on mailchimp
else if (!resolvedIDS[product])
{
resolvedIDS[product] = true
// adds product id as merge field becasue it doesn't exist
allProductIDPromises.push(
addMergeField(product,i)
)
}
}
// **** call Promise.all here, and return it
return Promise.all(allProductIDPromises);
}
)
然后,你应该删除这个:
allProductIDPromises.push( ... )
...并且由于您的主要三个承诺已经与 then
链接在一起,您只需要对最后一个承诺执行 then
:
updateMergeFields.then(function(addedMergeFields) {
// ... all is ready now.
}
最后,阅读您多次使用的 Promise constructor anti-pattern:您不应该使用 new Promise
,而实际上您可以 return 承诺(例如 return rp()
).