Bluebird Promise Retry DocumentDB request

2019-09-10 23:20发布

问题:

I'm trying to rewrite a retry function with callbacks into a Bluebird promise one but can't seem to get my head around the correct way of doing this. At the bottom is the working callback function for retrying Azure DocumentDB when limit is met. I'm trying to use promises in the function itself but it returns before reaching the "Then". Any hints on how to tackle this or if performance is affected by using catch this way would be appreciated. Thank you!

"readDocRetry": function(id, retries) {
                var self = this;
                return new Promise(function(resolve, reject){
                    self.client.readDocumentAsync(self.docsLink + id, null, function(err, data){
                        if (err) {
                            reject(err);
                        } else {
                            resolve(data)
                        }
                    }).then(function(results) {
                        console.log("ReadDocRetry result: " + results)
                         return results;
                    }).catch(function(err, headers) {
                        RetryError(self, id, err, headers, retries);
                    });

                });
            }

function RetryError(self, id, err, headers, retries) {
    if (err && err.code) {
        if (err.code === 429 && retries >= 0) {
            setTimeout(function() {
                self.readDocRetry(id, retries - 1); 
            }, Number(headers['x-ms-retry-after-ms'] || 1));
        }
        else if (err.code === 503 && retries >= 0) {
            setTimeout(function() {
                self.readDocRetry(id, retries - 1) 
            }, 500); 
        }
    }
    else if(err) {
        console.log(err); 
    }else{
        console.log("Err missing in RetryError");
    }
}


    bbCtx.readDocRetry("19").then(function(res){
        console.log("Hurrah!" + res);
    })

------- Working example with traditional callbacks which I'm trying to make promise based -----

    dbContext.prototype = {
        readDocRetry: function (id, retries, cb) {
            var self = this;
            self.client.readDocument(self.docsLink + id, function (err, results, headers) {
                if (err) {
                    if (err.code === 429 && retries >= 0) {
                        var aR = retries - 1;
                        setTimeout(function () {
                                self.readDocRetry(id, aR, cb);
                        }, Number(headers['x-ms-retry-after-ms'] || 1));
                    } else if (err && err.code === 503 && retries >= 0) {
                        var aR = retries - 1;
                        setTimeout(function () {
                                self.readDocRetry(id, aR, cb)
                        }, 500); 
                    } else {
                        cb(err); 
                    }
                } else {
                    cb(null, results);
                }
            });
        },

回答1:

When your catch callback is supposed to handle anything, it will need to return that new result like every other promise callback. In your case, it could return the promise for the result of the retry attempt:

function readDocRetry(id, retries) {
    var self = this;
    return new Promise(function(resolve, reject){
        self.client.readDocumentAsync(self.docsLink + id, null, function(err, data){
            if (err) {
                reject(err);
            } else {
                resolve(data)
            }
        });
    }).then(function(results) {
        console.log("ReadDocRetry result: " + results)
        return results;
    }).catch(function(err, headers) {
        if (err && err.code) {
            if (err.code === 429 && retries >= 0) {
                return Promise.delay(headers['x-ms-retry-after-ms'] || 1).then(function() {
                    return self.readDocRetry(id, retries - 1); 
                });
            } else if (err.code === 503 && retries >= 0) {
                return Promise.delay(500).then(function() {
                    return self.readDocRetry(id, retries - 1) 
                });
            }
        }
        if (err) {
            console.log(err);
            throw err;
        } else {
            console.log("Err missing in RetryError");
            throw new Error("rejection without error");
        }
    });
}