简体   繁体   中英

Using async.each with promises - async each never stops

I am building this function in node that is a mix of promises querying a DB and a async each. The issue is that the async.each function never stops. The promise2 function is never triggered. Is it an issue in my code or cant an async.each function be mixed with promises? Is there a better way to code what I want to do?

Thanks a lot for your help

promise1().then(function(arr1){
  async.each(arr1, function(obj1, callback) {
    build_select_request(obj1).then(function(select_request){
      query_database(select_request).then(function(result){
        if (result){                       
          build_update_request(obj1).then(function(update_request){                        
            do_query(update_request).then(function(result){                                          
              callback(null)
            }, function(error){
              callback(error)
            })
          }, function(error){
            callback(error)
          })
        } else {
          build_insert_request(obj1).then(function(insert_request){            
            do_query(insert_request).then(function(result){                                                                      
              callback(null)
            }, function(error){
              callback(error)
            })
          }, function(error){
            callback(error)
          })
        }
      }, function(error){
        callback(error)
      })
    }, function(error){
      callback(error)
    })
  }, function(err) {
    // if any of the file processing produced an error, err would equal that error
    if (err) {
      // One of the iterations produced an error.
      // All processing will now stop.
      reject(err)
    } else {
      promise2().then(function(success){        
        resolve(success)
      }, function(error){        
        reject(error)
      })
    }
  })
}, function(error){  
  reject(error)
})

Is it an issue in my code or cant an async.each function be mixed with promises?

It can, but it should not. Writing promise code and then falling back to callbacks results in, well, what you currently have.

Instead, make sure to use proper promise chaining:

var promise = build_select_request(obj1).then(function(select_request){
  return query_database(select_request).then(function(result){
    if (result){                       
      return build_update_request(obj1).then(do_query);
      /* .then(function(update_request){                        
        return do_query(update_request);
      }) */
    } else {
      return build_insert_request(obj1).then(do_query);
      /* .then(function(insert_request){            
        do_query(insert_request)
      }) */
    }
  })
})

You now can use that with async.each like this:

async.each(arr1, function(obj1, callback) {
  var promise = …;
  promise.then(function(result) {      
    callback(null, result)
  }, function(error) {
    callback(error);
  });
}, function(err) {
  …
})

but you better avoid this and instead use Promise.all which also lets you avoid the Promise constructor antipattern that you fell for (given the resolve / reject calls in your outermost callbacks):

promise1().then(function(arr1) {
  return Promise.all(arr1.map(function(obj1) {
    var promise = …;
    return promise;
  }));
}).then(function(results) {
  …
}, function(err) {
  …
});

I was missing "return"

promise1().then(function(arr1){
  async.each(arr1, function(obj1, callback) {
    build_select_request(obj1).then(function(select_request){
      return query_database(select_request).then(function(result){
        if (result){                       
          return build_update_request(obj1).then(function(update_request){                        
            return do_query(update_request).then(function(result){                                          
              callback(null)
            }, function(error){
              callback(error)
            })
          }, function(error){
            callback(error)
          })
        } else {
          return build_insert_request(obj1).then(function(insert_request){            
            return do_query(insert_request).then(function(result){                                                                      
              callback(null)
            }, function(error){
              callback(error)
            })
          }, function(error){
            callback(error)
          })
        }
      }, function(error){
        callback(error)
      })
    }, function(error){
      callback(error)
    })
  }, function(err) {
    // if any of the file processing produced an error, err would equal that error
    if (err) {
      // One of the iterations produced an error.
      // All processing will now stop.
      reject(err)
    } else {
      promise2().then(function(success){        
        resolve(success)
      }, function(error){        
        reject(error)
      })
    }
  })
}, function(error){  
  reject(error)
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM