【问题标题】:array of callbacks as Promise?作为 Promise 的回调数组?
【发布时间】:2019-10-15 09:34:18
【问题描述】:

我正在处理一些使用 RPC/YUI 库处理网络请求的旧代码。它本质上是创建标签来处理网络请求。这些都没有 Promise。另外,由于 IE11 支持,我们不能使用原生 Promise 对象。我们的构建过程不使用任何 NPM 依赖项,因此我们不能使用任何 babel 相关的 polyfill。

我正在努力修复一个错误,即每次另一个函数调用相同的函数时,参数ignoreError 都会被覆盖......显然!我们有多个函数调用这个网络请求函数库。有时我们想忽略错误,有时我们不想。

存储发出的多个请求及其各自的错误回调以便调用适当的项目的理想方法是什么?

示例:

var rpcUrl,
rpcRetries,
rpcIgnoreError;

// main function that sets some globals:
rpc: function(url, retries, ignoreError) {
  rpcUrl = url;
  rpcRetries = retries;
  rpcIgnoreError = ignoreError;
  this.doRpc();
},
// calls the YUI library to initialize network script:
doRpc: function() {
  YAHOO.util.Get.script(rpcUrl, {
    onFailure: function() {
      this.callbackError(true);
    },
    timeout: 55000
  });
},
// YUI callback
callbackError: function(retry) {
  if (retry && rpcRetries > 0) {
    rpcRetries = rpcRetries - 1;
    this.doRpc();
  } else {
    // ** how do i know this error handling is for the script which failed?
    if (!rpcIgnoreError) {
      this.populateFormStatus(6);
    }
  }
},

现在,我们有多个函数调用rpc(),例如:

sendConfig: function() {
  this.rpc(urlForEndpoint, 3, true);
},
sendUser: function() {
  this.rpc(urlForEndpoint, 3, false);
},
sendWidget: function() {
  this.rpc(urlForEndpoint, 3, false);
},

我担心创建一个回调数组并不能保证每个项目都由其各自的处理程序处理。

我可以做一些事情,比如创建一个地图常量:

var RPC_ERR_CB = {
    sendConfig: false,
    sendUser: true,
    sendWidget: true
};

//然后在onFailure回调中,可以读取到脚本标签的src

...
doRpc: function() {
  YAHOO.util.Get.script(rpcUrl, {
    onFailure: function() {
      var hasCB = Object.keys(RPC_ERR_CB).some(function(item) {
        return arguments[0].src.indexOf(RPC_ERR_CB[item]) <= 0;
     });
      if (hasCB) {
        this.callbackError(true);
      }
    },
    timeout: 55000
  });
},

希望这是有道理的...谢谢!

【问题讨论】:

  • 您是否需要等到每个呼叫都已解决? - 他们是顺序解决还是并行解决
  • 不,我们不需要这个功能。
  • “我担心制作一个回调数组并不能保证每个项目都由其各自的处理程序处理。”是什么意思?据我所知,只有一个处理程序 (callbackError)。
  • 你可以简单地做this.doRpc (ignoreError)this.callbackError (true, ignoreError)
  • 但是您的所有变量都存在相同的问题,您可能希望将 url 与对象内的这些选项一起存储,将其保存在类实例中的某个位置,或者按照您在额外查找。

标签: javascript rpc yui


【解决方案1】:

您可以将值传递给doRpc,然后您可以将其传递给callbackError 或在doRpc 中处理它(就像您最后的示例代码一样)。这将防止全局变量在您身上发生变化。

【讨论】:

    【解决方案2】:

    如果您无法使用 Promises 或 ES6 类,您的选择就会变得有限。如果可能的话,我建议硬着头皮获得 Babel 转译过程,这样您就可以利用更新的功能而无需放弃对 IE11 的支持。

    尽管如此,理想情况下,您不希望在某个地方跟踪全局变量中的每个请求。您可以通过将每个请求创建为自包含对象来独立处理每个事务:

    function RpcRequest (url, retries, ignoreError) {
      this.url = url
      this.retries = retries
      this.ignoreError = ignoreError
    }
    
    RpcRequest.prototype.send = function() {
      YAHOO.util.Get.script(this.url, {
        onFailure: function() {
          this.callbackError(true);
        },
        timeout: 55000
      });
    }
    
    RpcRequest.prototype.callbackError = function(retry) {
      if (retry && this.retries > 0) {
        this.retries = this.retries - 1;
        this.send();
      } else {
        if (!this.ignoreError) {
    
          // ...
    
        }
      }
    }
    
    // Somewhere else, initiate a request
    var requestOne = new RpcRequest("http://blah", 3, false)
    requestOne.send()
    

    我在查看您的代码时注意到的一点:创建请求的代码不知道请求是否成功。当你遇到错误时,调用上下文对该错误一无所知。我查看了您提到的库,它似乎确实有一些您可以传递的上下文。

    如果我稍微重写一下,我会做这样的事情来将错误冒泡到你的调用上下文:

    RpcRequest.prototype.send = function(callback) {
      YAHOO.util.Get.script(this.url, {
        onFailure: function(context) {
          if( this.ignoreError ) {
            context.ignoredError = true
            callback(null, context);
            return;
          }
    
          var retError = new Error('Failure doing something!');
          retError.context = context;
    
          callback(retError);
        },
        onSuccess: function(context) {
          callback(null, context);
        },
        timeout: 55000
      });
    }
    
    // Somewhere else in the code...
    sendWidget: function() {
      var request = new RpcRequest(urlForEndpoint, 3, false)
      request.send(function(err, result) {
        if( err ) {
          console.error('Failed at doing a widget thing:', err.context);
          // maybe even:
          // throw err;
          return;
        }
    
        if( result.ignoredError ) {
          console.warn('Ignored an error on the widget thing:', result);
          return;
        }
    
        console.log('Success on the widget thing!', result);
      })
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-24
      • 2016-07-01
      • 2019-01-07
      • 2018-04-23
      • 1970-01-01
      • 2012-08-03
      相关资源
      最近更新 更多