函数在回调返回结果之前完成

时间:2017-01-11 12:16:03

标签: javascript node.js asynchronous

我是节点的新手,我正在做一个随机练习,回调和异步处理对我来说是新的。在解释如何完成这项任务时,我将不胜感激。

我要做的是根据从Excel电子表格中获取的行创建一个对象,并通过在我的表格中添加/更新它们来单独处理它们。

我遇到的问题,我看到的问题与节点新手很常见,并不了解如何同步处理。

我不明白为什么默认情况下会异步运行,当然大部分时间你都希望在执行另一个操作之前发生某些事情?

我可能没有正确接近这个? 在这种情况下,我从excel数据集中获取一行,因为我循环遍历数据集,我为每一行创建一个对象,其中一部分涉及对另一个函数(getAreaId)进行回调以获取基于该对象的area_id areaCode已通过。在我的控制台日志中,myOrganisation对象始终将areaCode显示为undefined。

当我在回调函数中使用console.log时,我看到显示的是正确的值。将回调返回的值分配给本地对象的最佳方法是什么?

我读过我需要添加一些像async这样的中间件。由于这是我在节点上的第一次尝试,我不想开始潜入添加库或使事情变得更复杂,如果我不需要。

function importData(){
    var myDataSet = getExcelData();
    var x = getOrganisationCode(function(existingOrgCode){

        for (j=0; j<myDataSet.length; j++){

            function organisationObj(orgCode, orgName, address1, areaCode){
                this.orgCode  = orgCode;
                this.orgName  = orgName;
                this.address1 = address1;
                //this.areaId   = getAreaId(areaCode, function(area_id){ return area_id});
                getAreaId(areaCode, function(area_id){ this.areaId = area_id});
            }

            myOrganisation =  new organisationObj(myDataSet[j]['OrgCode'], myDataSet[j]['OrgName'], myDataSet[j]['orgName'], myDataSet[j]['areaCode']);

            console.log(myOrganisation)

            if(isNewOrg(existingOrgCode.indexOf(myOrganisation.orgCode))){
                //doInsert
            } else {
                //doUpdate
            }
        }
    });
}

function getExcelData(){
    //This gets data from an excel spreadsheet
}

function isNewOrg(orgCode){
    //Checks if orgCode is not -1 and returns true/false accordingly
}

function getOrganisationCode(callback){
    //Do a DB call to return all orgCodes
    //SELECT orgCode FROM tOrg
}

function getAreaId(areaCode, callback){
    //Do a DB call to return an area id based on the code passed
    //SELECT areaId FROM tAreas WHERE areaCode = @input_parameter
}

2 个答案:

答案 0 :(得分:1)

每当进行异步调用时,操作都会与当前代码流并行执行。

如果执行异步数据库调用,则程序不会等待数据库完成。这就是使用回调的原因。

你只需告诉数据库:“嘿,给我一个身份证明。当你完成时告诉我。我会同时处理其他一些事情。” 然后你的程序继续并退出getAreaId函数。一段时间后,数据库给你回电“嘿,这是id。”并为回调函数提供id。

organisationObj
    --> getAreaId
        |   --> db call
    <-- |          |
...                |
...                |
 (callback) <------|

答案 1 :(得分:1)

Rita Saxena已经分享了一个很好的链接来解释异步。

代码中的主要问题是循环中存在异步调用getAreaId。

了解async概念的更一般解释(作为Riya Saxena共享的补充),想想这个函数

for(var i = 1; i <= 5; i++) {
  setTimeout(function() {
   console.log('Value of i : ' + i); 
  },100);
}

您可能希望输出为:

Value of i : 1
Value of i : 2
Value of i : 3
Value of i : 4
Value of i : 5

但实际输出是:

Value of i : 6
Value of i : 6
Value of i : 6
Value of i : 6
Value of i : 6

这是因为在评估 setTimeout 时,循环已完成,在循环评估结束时保留 i 的值。

此示例可以通过不回答此问题的不同方式进行修复。

在您的情况下,当评估 console.log(myOrganisation)时,

myOrganisation =  new organisationObj(myDataSet[j]['OrgCode'],
                   myDataSet[j]['OrgName'], myDataSet[j]['orgName'],
                   myDataSet[j]['areaCode']);

尚未从评估中返回(db call)

作为一般准则,在混合循环和异步调用时要小心。