【问题标题】:Manipulating data in a callback function在回调函数中操作数据
【发布时间】:2016-12-15 16:37:03
【问题描述】:

我有一个嵌套函数,它执行一些 I/O 并在完成结果数据后调用回调。像这样的:

function getStatus(returnCallback, errorCallback) {
   sendRequest('someData', returnCallback, errorCallback)
}

其中 sendRequest() 是一个与硬件交互的函数,并使用从硬件获得的数据调用 returCallback 或 errorCallback 以防出现问题。 我现在的问题是,硬件返回的数据是一个非常长的字符串,由代表不同参数的不同数字组成。我想要做的是操纵提供给 returnCallback 的数据,并为每个参数创建一个具有属性的对象。有没有办法做到这一点?我已经尝试过使用 async.waterfall

function getStatus(returnCallback, errorCallback) {
        let returnArray = {};
        async.waterfall([
            function (callback) {
                sendRequest('someData', callback, errorCallback);
            },
            function (data, callback) {
                returnArray.statusBits = data.slice(0, 6);
                returnArray.faultBits = data.slice(7, 13);
                returnArray.alertBits = data.slice(14, 20);
                returnArray.pumpRotationSpeed = parseInt(data.slice(21, 26));
                returnArray.motorPower = parseInt(data.slice(27, 31));
                returnArray.frequencyConverterTemperature = parseInt(data.slice(36, 39));
                returnArray.pumpOperationTime = parseInt(data.slice(44, 48));
                callback(null, returnArray)
            }
        ], returnCallback(returnArray));

但这无济于事。看起来瀑布中的第二个函数从未被调用过。这可能是因为第一个函数的回调在瀑布中的结构不符合预期,它返回 callback(data) 而不是 callback(null, data)

【问题讨论】:

    标签: javascript node.js asynchronous callback waterfall


    【解决方案1】:

    async.waterfall回调中,第一个参数是error,另外,你应该在退出函数之前等待瀑布结束。正确的代码是:

    function getStatus(returnCallback, errorCallback) {
        let returnArray = {};
        async.waterfall([
            function (callback) {
                //First step
                sendRequest('someData', function (data) {
                    //Everything is fine, continue
                    callback(null, data);
                }, function (error) {
                   //Error, skip all remaining step, and handle the error
                    callback(error);
                });
            },
            function (data, callback) {
                //Second step
                returnArray.statusBits = data.slice(0, 6);
                returnArray.faultBits = data.slice(7, 13);
                returnArray.alertBits = data.slice(14, 20);
                returnArray.pumpRotationSpeed = parseInt(data.slice(21, 26));
                returnArray.motorPower = parseInt(data.slice(27, 31));
                returnArray.frequencyConverterTemperature = parseInt(data.slice(36, 39));
                returnArray.pumpOperationTime = parseInt(data.slice(44, 48));
                callback(null, returnArray)
            }
        //In normal case, error will be null, and the param will be the last passed to the callback of the last step
        ], function (error, returnArray) {
            //If there is a error (like error in step 1)
            if(error) {
                //Handle the error
                errorCallback(error);
            } else {
                //No error, continue with the normal callback
                returnCallback(returnArray);
            }
        });
    }
    

    【讨论】:

    • 实际上有没有办法整合我有第二个负责错误的回调函数这一事实?所以当 sendRequest 返回错误时瀑布停止?类似sendRequest('someData', functon (data) {callback(null, data)}, function (error) {callback(error, null)})
    • 你不会像瀑布那样那样做,目标是走到瀑布的尽头,如果出错则跳过所有剩余的步骤,或者传递,然后在结束时瀑布,检查错误并处理它们。
    • 是的,我就是这个意思。我的函数有两个回调,如果没有大量的工作我无法改变它。如何让 async.waterfall 知道 sendRequest 函数中发生了错误(调用了 errorCallback 而不是 returnCallback)以便它跳到最后?
    • 不直接调用errorCallback,而是传递一个匿名回调来传递错误,因为会传递一个错误,waterfall会跳到最后,所以你可以调用你的错误回调。看看我的编辑,它应该是你需要的:)
    【解决方案2】:

    你想做的是

    处理返回回调的数据并创建和 每个参数都有一个属性的对象。

    你有

    function getStatus(returnCallback, errorCallback) {
       sendRequest('someData', returnCallback, errorCallback)
    }
    

    如果我明白你想要做什么,

    function getStatus(function(err, status) {
       if (err) return new Error('Something went wrong');
       else  sendRequest(status);
    }
    //get what you need here
    var status = ... )
    

    这里,getStatus 函数首先在并行进程中执行回调函数。 statuserr 参数将作为占位符放置在内存中。同时,getStatus 正在做他需要做的事情来检索您想要的状态并将其存储为变量。读取完成后,结果将放在并行进程的占位符中,然后执行完成。

    这种异步方法源于您正在硬件内部读取数据并且需要一些时间来检索它。同步方式会阻塞任务并等待每一步完成,而异步方式允许不阻塞每一步,而是在完成之前的任务时启动其他任务。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-18
      • 1970-01-01
      • 2014-10-01
      • 1970-01-01
      • 2017-12-14
      • 2018-09-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多