回调数组是否为Promise?

时间:2019-05-29 18:00:13

标签: javascript rpc yui

我正在研究一些旧的旧代码,这些代码使用RPC / YUI库处理网络请求。本质上,它创建标签来处理网络请求。这些都没有承诺。此外,由于支持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
  });
},

希望这很有道理...谢谢!

2 个答案:

答案 0 :(得分:1)

您可以将值传递到doRpc,然后可以将其传递到callbackError或在doRpc中进行处理(如最后的示例代码)。这样可以防止全局变量对您造成影响。

答案 1 :(得分:1)

如果您不能使用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);
  })
}