麻烦与js诺言(蓝鸟)

我试图从列表中创buildMailChimp中的合并域,如果它们不存在。 如果他们不存在,我希望他们被推到承诺的列表,我使用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 } 

NB:我正在使用请求承诺来提出我的请求,所以他们已经promisified。

getMergeFieldsPromisecallback没有返回任何东西,所以一旦getMergeFieldsPromise被parsing,它不会等待addMergeField承诺,而是立即parsing(与undefined为承诺值)。

为了解决这个问题,使allProductIDPromises在当前callback中allProductIDPromises一个局部variables,并调用Promise.all ,并将其返回

 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( ... ) 

…因为你的主要三个承诺已经被链接在一起,你只需要在最后一个执行一个:

 updateMergeFields.then(function(addedMergeFields) { // ... all is ready now. } 

最后,阅读有关Promise构造函数的反模式 ,您可能会多次使用该模式 :实际上,您可以返回一个promise(例如return rp() ),但不应该使用new Promise