【问题标题】:Proper way to loop for a promise response循环以获取承诺响应的正确方法
【发布时间】:2019-07-06 05:12:04
【问题描述】:

我的应用程序有一个主要和次要的短信服务。如果主要失败,对于任何问题,我想默认使用辅助服务。

流程如下:

  1. 发送到短信服务
  2. 短信服务以收到确认响应
  3. 短信服务向电话运营商发送消息
  4. 短信服务收到电话运营商收据
  5. 然后我的应用可以查询短信服务以获取运营商收据

但是,由于涉及的时间范围(互联网、运营商延迟等),我需要循环 #5 直到运营商收据进入...或超时...以确定它是否需要转到二级服务。目前,我在查询 #5 之前执行了 3 秒的超时延迟 - 但我想将其转换为 1 秒循环,以确保如果 #4 花费的时间超过 3 秒,我的 #5 仍然可以正常工作。

  $scope.sendCode = function() {
    $scope.errColor = "red" ;
    $scope.errMsg = "SENDING AUTH CODE" ;
    var newCode = getRandom(10000,99999) ;
    //var tktCode = new Date().format("yyyymmdd")+ "_" +getRandom(10000,999999) ;
    var smsNumber = getDB("user_phone") ;
    setDB("app_regCode",newCode) ;
    var msg = "App registration code: "+newCode+ ". Enter this code into the 'VERIFY CODE' input field" ;
    var tReq = twilio(smsNumber,msg) ;

    var smsCarrier = getDB("dev_carrier") ;
    if (!smsCarrier) {
      smsCarrier = "No Carrier Info" ;
    }
    var smsEmail = $scope.userObj.user_email ;
    if (!smsEmail) {
      smsEmail = "No Email" ;
    }

    $scope.errColor ;
    $scope.errMsg ;
    var error = {} ;  
    var smsShortCode = vendorData.twilioShortCode ;
    var smsLongCode = vendorData.twilioLongCode ;  
    // log message sent to internal API
    $scope.smsID = logSMS(smsNumber,smsLongCode,smsShortCode,msg,smsCarrier,smsEmail,"Twilio") ;
    $http(tReq).then(function(response) {
      $scope.errColor = "green" ;
      $scope.errMsg = "SENT!  Confirming Delivery" ;
      smsResponse = response.data ;
      if (smsResponse.sid) {
        //update smsSent record
        apiService.all("PUT",[{table:"smsSent",sid:"rid",sidValue:$scope.smsID,soloField:1,dataInfo:{smsTkt:smsResponse.sid}}]) ;
      }
      if (smsResponse.status.match(/(queued|accepted|sending|sent)/i)) {  //if (sms.success == true) {

        // need to replace this with a proper 1 second loop
        // to test for "delivered" carrier receipt
        // if status still (queued|accepted|sending|sent), then loop until its updated
        // final receipt statuses are: Delivered, Undelivered, Failed

        setTimeout(function() {  
          return $http(twilioVerify(smsResponse.uri))
          .then(function(response) {
            // now check status of message to determine if needed to exit or go to back up service
            //return $http(twilioVerify(smsResponse.uri))
            if (response.data.status == "delivered") {
              $scope.errColor = "green"
              $scope.errMsg = "Delivery Confirmed" ;
              messageSent('Primary');
            } else {
              //backup service
              // determine fail reason, send to secondary if necessary
              messageFail('Primary') ;
              $scope.errColor = "red"
              $scope.errMsg = "Problem detected, trying secondary service" ;              
              secondSMS(smsNumber,msg) ;
            }
          }) ;
        },3000) ;

      } else {  // failed response from Twilio, send to MissionMobile
        $scope.errColor = "red" ;
        $scope.errMsg = "Problem detected, attempting secondary service"
        messageFail('Primary') ;
        secondarySMS(smsNumber,msg) ;
      }
    }, function(thisError) {  // failed communication to Twilio, send to MissionMobile
        $scope.errColor = "red" ;
        $scope.errMsg = "Issue sending code, attempting secondary service" ;
        messageFail('Primary') ;
        secondarySMS(smsNumber,msg) ;
    }).catch(function(error) {
        $scope.errColor = error.errColor ;
        $scope.errMsg = error.errMsg ;
    }) ;
  }

【问题讨论】:

  • 不确定这是否是问题所在,只是在您的代码中发现了错误。如果你有 setTimeout,return 里面就不行了。您需要在 AngularJS 或原生 Promise 中使用库 $q 创建显式 Promise,在 setTimeout 之外返回该 Promise 并在内部解决/拒绝它。
  • 在旁注中,不要使用setTimeout 而更喜欢$timeout,因为它属于角度摘要循环。核心 JS 函数与 angularjs 一起使用并不是一件好事
  • @ShashankVivek - 是的。我正在使用 $timeout 并切换到 setTimeout 进行测试。但最终我需要摆脱超时并用某种循环替换。

标签: javascript angularjs loops cordova promise


【解决方案1】:

使用$interval 怎么样:

    final_check_interval = $interval(function() {  
      return $http(twilioVerify(smsResponse.uri))
      .then(function(response) {
        // now check status of message to determine if needed to exit or go to back up service
        //return $http(twilioVerify(smsResponse.uri))
        if (response.data.status == "delivered") {
          $scope.errColor = "green"
          $scope.errMsg = "Delivery Confirmed" ;
          messageSent('Primary');
        } else {
          //backup service
          // determine fail reason, send to secondary if necessary
          messageFail('Primary') ;
          $scope.errColor = "red"
          $scope.errMsg = "Problem detected, trying secondary service" ;              
          secondSMS(smsNumber,msg) ;
        }
      }) ;
    },1000) ;

messageSent() 上,请确保取消每 1 秒触发一次的时间:

$interval.cancel(final_check_interval);

我希望你知道你在寻找什么

【讨论】:

  • 工作就像一个魅力......谢谢!我添加了一个循环计数器 5...else if (response.data.status.match (/(undelivered|failed)/i) || counter = 5)) { //cancel } 以在 5 秒后超时并自动默认为辅助服务。
  • @rolinger 太棒了!
猜你喜欢
  • 2017-02-01
  • 2019-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-26
  • 2018-05-08
  • 2018-01-28
相关资源
最近更新 更多