0

I want to chain my promises depending upon if the previous call was resolved or rejected. I am making a call to server in all promises. So, I am writing it like-

apiServices.patientsSearch(id)
.then(function(data){
    return callback(null,data);
},function(err){
    return apiServices.studiesSearch(id);
}).then(function(data){
    return callback(null,data);
},function(){
    return apiServices.seriesSearch(id); 
}).then(function(data){
    return callback(null,data);
})
.catch(function(err){
    return callback(false,err);
});

As every then returns a promise object, problem is that catch is always being called if any promise except the last one calls resolve. One way I am thinking is to check if err is empty and ignore it. Is it the right way to do it ?

I am using request module, if I set forever: true, I start getting-

{ [Error: socket hang up] code: 'ECONNRESET' }

With forever false, it works. Why my socket is still busy even after the request has ended ? As the next request will go only when reject is called, so socket should be free by that time.

Krrish Raj
  • 1,505
  • 12
  • 28
  • What is `callback(null, data)`? – Bergi Mar 29 '17 at 09:38
  • @Bergi callback function to pass data to controller with error or result. – Krrish Raj Mar 29 '17 at 09:41
  • I didn't understand `that catch is always being called if any promise except the last one calls resolve` . Can you explain a bit more? – John Mar 29 '17 at 09:41
  • "*catch is always being called if any promise except the last one calls resolve.*" makes no sense to me. The `catch` callback is *only* called if one of the last two `callback(null, data)` or `apiServices.seriesSearch(id)` reject. – Bergi Mar 29 '17 at 09:41
  • @krrish I don't think you are supposed to call the `callback` multiple times? – Bergi Mar 29 '17 at 09:41
  • @JohnJoseph Somehow my catch block is always executed. I think that is happening because even if my very first Promise resolves and callback is called, the next chained resolve will be called again with null value as every then returns a promise object. In the next resolve, again callback will be called, which I think is throwing some exception like header already sent or something and so catch is executed again. I am very new to promises, so this is what I can think off. – Krrish Raj Mar 29 '17 at 10:11
  • @Bergi I also think that I should just return the data in all resolves except the last one and call the callback in last resolve, as the data will be eventually propagated to last block. This should also take care of my catch block being called always. Correct me if I am wrong. – Krrish Raj Mar 29 '17 at 10:13
  • Yes, exactly this. – Bergi Mar 29 '17 at 10:19
  • Looks like a classic candidate for a [catch reduction](http://stackoverflow.com/documentation/javascript/231/promises/5917/reduce-an-array-to-chained-promises#t=201703300416582396396). – Roamer-1888 Mar 30 '17 at 04:20

1 Answers1

1

You should only call the callback once. Don't pass it as the onfulfilled-handler after each promise, call it once in the end:

apiServices.patientsSearch(id).then(null, function(err){
    return apiServices.studiesSearch(id);
}).then(null, function(){
    return apiServices.seriesSearch(id); 
}).then(function(data){
    callback(null,data);
}, function(err){
    callback(false,err);
});

or

apiServices.patientsSearch(id).catch(function(err){
    return apiServices.studiesSearch(id);
}).catch(function(){
    return apiServices.seriesSearch(id); 
}).then(function(data){
    callback(null,data);
}, function(err){
    callback(false,err);
});

Of course, you shouldn't be calling any callbacks at all in promise-based code, so use this only if you have to interface with legacy code. Otherwise, don't take a callback parameter and just return the promise:

return apiServices.patientsSearch(id).catch(function(err){
    return apiServices.studiesSearch(id);
}).catch(function(){
    return apiServices.seriesSearch(id); 
});
Bergi
  • 630,263
  • 148
  • 957
  • 1,375