如何重新运行Promise直到一个条件

时间:2017-08-10 19:06:30

标签: javascript node.js asynchronous promise es6-promise

我需要实现以下逻辑。

我需要下载图片,但有时候下载的文件已损坏,所以我需要再次尝试下载。以下是我的下载承诺的样子。

return Downloader.downloadImage(downloadUrl, fileName).then((filename) => {
            // Update some info, save ... and return new promise
            return doStuffAndReturnPromise(filename);
        });

但正如我上面所描述的,我需要验证下载的文件是否是有效的图像,然后才能成功返回承诺。

这是一个骨架。

 return new Promise(function (resolve, reject) {
            let retryCounter = MyService.RETRY_COUNT;
            let success = false;
            while (retryCounter > 0 && !success) {
                 // Run new promise but wait until it completes
                 // Decrease the counter
                retryCounter--;
            }
        });

这里的问题是我需要同步运行下载承诺,然后继续迭代并运行新的承诺。

请建议优雅地解决此问题的最佳方法。

感谢。

3 个答案:

答案 0 :(得分:0)

你可以返回一个再次尝试的Promise而不是answear,如下所示:

import paramiko
import time

def ssh_session(ip):
    try:
        session = paramiko.SSHClient() #Open the session
        session.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        session.connect(ip, username = "ciscouser1", password = "password")
        connection = session.invoke_shell()

        ####Running Cisco IOS commands###
        connection.send("enable\n")
        connection.send("password1") #sending
        connection.send("\n")
        connection.send("configure terminal\n\n")
        time.sleep(1)
        connection.send("do show ip int brief\n")
        time.sleep(1)
    except paramiko.AuthenticationException:
        print "wrong credentials"
ssh_session("10.10.10.1")

您可以像这样使用它:

var maxAttempts = 5
var counter = 0

return Downloader.downloadImage(downloadUrl, fileName).then((filename) => {
    // Update some info, save ... and return new promise
    if (checkIfNeedToTryAgain()) {
        counter++;
        if (counter > maxAttempts) {
            throw maxAttemptsError
        }
        // Try again
        return Downloader.downloadImage(downloadUrl, fileName)
    }
    // In case of success
    return doStuffAndReturnPromise(filename);
}); 

答案 1 :(得分:0)

我在前一段时间(http://jsbin.com/xefutos/6/edit?html,js,output)写了这个例子,你应该能够根据自己的需要进行调整:

// Function that returns a promise
var searchForNumber = function(number) {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        var min = 1;
        var max = 10;
        var val = Math.floor(Math.random()*(max-min+1)+min);

        console.log('Value is: ' + val.toString());        

        return resolve(val);        
      }, 1000);
    });
};

// fn     : function that should return a promise.
// args   : the arguments that should be passed to fn.
// donefn : function that should check the result of the promise
//    and return true to indicate whether ploop should stop or not.
// promise: A promise value that is used internally by ploop and should never 
//    be passed in by the caller of ploop.
var ploop = function(fn, args, donefn, promise) {
    return (promise = promise || Promise.resolve(true))    
      .then(function() {
          return(fn.apply(null, args));
      })
      .then(function(result) {
        var finished = donefn(result);
        if(finished === true){
           return result;
        } else {
          return ploop(fn, args, donefn, promise);
        }
    });
};

var searchFor = 4;

var donefn = function(result) {
  return result == searchFor;
};

console.log('Searching for: ' + searchFor);
ploop(searchForNumber, [searchFor], donefn)
  .then(function(val) {
    console.log('Finally found! ' + val.toString());  
    process.exit(0);
  })
  .catch(function(err) {
    process.exit(1);
  });

答案 2 :(得分:0)

我发现Observer模式在这些场景中非常有用,因为它使代码更具可读性和可重用性。这是代码的样子

// MyObservable.js
var util = require('util');
var EventEmitter = require('events').EventEmitter;

function MyObservable() {
  EventEmitter.call(this);
}

MyObservable.prototype.downloadImage = function(imageUrl) {
  // download image code and validate
  if (imageIsValid) {
    this.emit('done', 'valid image');
  } else {
    this.emit('error', 'invalid image')
  }
}

以上是下载代码。国际海事组织,它在未来也更可重复使用,或者有不同的观察员对其采取行动。

const MyObservable = require('./MyObservable');

const observable = new MyObservable();


let retryCount = 3;
observable.on('done', (message) => {
  console.log('Download completed');
});
observable.on('error', (message) => {
  retryCount -= 1;
  if (retryCount > 0) {
    observable.downloadImage(imageUrl);
  }
});
observable.downloadImage(imageUrl);