如何在一个具有不同参数的连续调用两次的javascript中为函数添加回调?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在一个具有不同参数的连续调用两次的javascript中为函数添加回调?相关的知识,希望对你有一定的参考价值。

我有一个使用不同参数调用两次的函数:

function setArray(chartType, charData, nodeName, meaQuantityId, unitName) {
  var legendText = nodeName + '(' + unitName + ')';
  var lineData = null;
  var scatterData = null;
  if (chartType != null) {
    switch (chartType) {
      case 'line':
        {
          if (compareGraphData.length > 0) {
            for (var i = 0; i < compareGraphData.length; i++) {
              if (legendText == compareGraphData[i].legendText) {
                legendText = changeLegendText(legendText, i);
              }
            }
          }
          lineData = {
            type: chartType, //try changing to column, area
            showInLegend: true,
            legendText: legendText,
            toolTipContent: "{label}LS : {y} ",
            dataPoints: charData
          };
          compareGraphData.push(lineData);
          break;
        }
      case 'scatter':
        {
          if (compareScatterGraphData.length > 0) {
            for (var i = 0; i < compareScatterGraphData.length; i++) {
              if (legendText == compareScatterGraphData[i].legendText) {
                //legendText = changeLegendText(legendText, i);
              }
            }
          }
          scatterData = {
            type: chartType, //try changing to column, area
            showInLegend: true,
            legendText: legendText,
            toolTipContent: "{label}LS : {y} ",
            dataPoints: charData
          };
          compareScatterGraphData.push(scatterData);
          break;
        }
    }
  } else {
    var arr = [];
    for (var i = 0; i < charData.length; i++) {
      arr.push({
        'quantityName': charData[0].nodeName,
        'data': charData[i].value,
        'count': charData[0].count,
        'unitName': charData[0].xUnitName,
        'meaQuantityId': meaQuantIdForDataTable
      });
    }
    dataView.push(arr);
  }
}

function changeLegendText(legendText, i) {
  var value = webix.ui({
    view: "window",
    modal: true,
    id: 'id-win-change-channel-Name',
    fullscreen: true,
    position: function(state) {
      state.width = 220;
      state.top = 200;
      state.left = (window.innerWidth - state.width) / 2;
      state.height = 150;
    },

    head: "Change Alias!",
    body: {
      padding: 10,
      rows: [{
        view: 'text',
        id: "id-text-change-channel-Name",
        value: legendText + '_' + i
      }, {
        view: 'button',
        value: "OK",
        click: function() {
          channelAliasValue = $$('id-text-change-channel-Name').getValue();

          $$('id-win-change-channel-Name').hide();
        }
      }]
    }
  }).show();
}

////I call the function like this:

DBService.getGraphData('getGraphData')
    .then(function(response){
    var charData=response.result;
    setArray('line', charData, nodeName, meaQuantityId, unitName);
    setArray('line', charData, nodeName, meaQuantityId, unitName);
});
I have compared legendText with the one in the compareGraphData array. If it is true then a popup comes up with a text box and a button.

我希望在弹出窗口出现时停止执行,并在用户单击按钮后继续执行。

但上面的代码不会等待用户事件并继续下一个语句。

你能告诉我实现这个目标的最佳方法吗?

答案

您可以将函数传递给您的函数,如下所示:

function setArray(chartType, data, cb){
 cb("hello")
} 

setArray('scatter', data, function(x){
 console.log(x) // hello
});

function setArray(chartType, data, cb){
 cb(data)
} 

setArray('scatter', "Hello ", function(x){
 setArray('scatter', "World!", function(y){
    console.log(x + y)// Hello world!
 })
});

或使用async

另一答案

在异步执行的情况下(缺少setArray函数体的情况不明确),这可以通过promises解决。参考这里:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

let setArray = function setArray('line', data) {
  return new Promise((resolve, reject) => {
    // logic for function setArray here
  });
};

let call1 = setArray('line', data).then(function(result) {
  // do stuff with result
});

let call2 = setArray('scatter', data).then(function(result) {
   // do stuff with result
});
另一答案

我想你想要的只是使用最后的改变。

例如,用户具有所有动物的列表,并且可以选择仅显示慢动物或快动物但过滤器是异步的。

用户单击以仅显示慢动物,过滤器返回数据需要1秒钟。在这一秒内,用户选择显示所有动物,因此用户界面设置为显示所有动物。显示全部需要100毫秒,返回并更新列表以显示所有内容。然后慢动物列表进来,列表只显示慢动物。

现在,用户界面和显示的列表不同步。 here描述了这个问题。

我实现的这个问题的solution是将一个promise传递给一个函数,如果它是最后创建的promise(最近的用户操作),它只会解析promise。

如何将使用回调的函数转换为返回promise的函数可以找到here(在:将回调转换为promise。)

[UPDATE]

如昨天所述;我认为用户更改了某些内容然后更改了其他内容,因此2个承诺正在获取在用户创建它们的同时无法解析的数据和/或两者都在解析,因此您的应用程序正在执行不再需要的操作。

我昨天给出的答案可以使用lib中的onlyLastPromise以下列方式应用于您的代码:

const onlyLastRequestedPromise = ((promiseIds) => {
  const whenResolve = (promise, id, promiseID, resolveValue) => {
    if(promise!==undefined){//called by user adding a promise
      promiseIds[id]={};
    } else {//called because promise is resolved
      return (promiseID === promiseIds[id])
        ? Promise.resolve(resolveValue)
        : Promise.reject("A newer request was made.")
    }
    return (function (currentPromiseID) {
      return promise
        .then(function (result) {
          return whenResolve(undefined,id, currentPromiseID, result);
        });
    }(promiseIds[id]));
  };
  return (id = "general") => promise =>
    whenResolve(promise, id);
})({});
//this is for your fetching your data, add it to your service
const lastForChart=onlyLastRequestedPromise("CHART_DATA");

//wrap your getGraphData in a "only last"
lastForChart(DBService.getGraphData('getGraphData'))
.then(
  function(response){
    var charData=response.result;
    setArray('line', charData, nodeName, meaQuantityId, unitName);
    setArray('line', charData, nodeName, meaQuantityId, unitName);
})
.catch(
  err=>
    (err==="A newer request was made.")
      ? "replaced by newer request"
      : Promise.reject(err)
);

以上是关于如何在一个具有不同参数的连续调用两次的javascript中为函数添加回调?的主要内容,如果未能解决你的问题,请参考以下文章

在页面中包含两次的脚本中调用函数

解决onActivityResult方法调用两次的问题

vue mounted 调用两次的解决办法

用不同的语言编译同一个文件两次的惯用方法是啥?

带字符串的正则表达式:出现两次的字母对[关闭]

在mysql中以不同月份显示相同数据(或值)两次的查询