2014-02-27 34 views
2

我正在开发一个Phonegap应用程序,它依赖于从不同文本文件中将多个值加载到应用程序中,然后才能正确运行。我认为我正确使用回调函数来解决JS的异步性质,但是我的程序输出告诉我代码被调用的顺序相反...Javascript回调函数没有按预期发射

在这段代码运行中,我已经设置了唤醒时间 - 这也设置了就寝时间 - 并将两个值都保存到文本文件中。

调用的顺序应该是这样的:

Determine if the user is a new user or not... output is not necessary for other parts of application 

Determine if the user has entered a waketime in the application before, if so read that time from the relevant text file, if not then use default wake & sleep time 

Once we have the correct wake & sleep times, clear all previous notifications from notification queue 

Once all previous notifications have been cleared, add new notifications for the current day within the time between waketime and bedtime... this is dependent on the bedtime and waketime already being determined 

Concatenate all of the notification times generated into a string 

Write this concatenated string to a text file 

相关JavaScript变量初始化:

var defaultWakeTime = moment().hours(8).minutes(0).seconds(0); 
    var defaultBedTime = moment().hours(23).minutes(0).seconds(0); 

    //variables used to determine notification beginning and end range: 
    var wakeTimeDate; 
    var bedTimeDate; 
在onDeviceReady

():

function onDeviceReady() { 
     console.log("WITHIN onDeviceReady()"); 

     document.addEventListener("pause", userHasGoneIdle , false); 
     document.addEventListener("backbutton", onBackKeyDown, false); 

     determineWhichLogin(); 

     determineWakeTimeBedTime(clearPriorNotifications(addNewNotifications)); 

     formNotificationString(writeToNotificationFile); 
    } 

功能代码:

01 addNewNotifications内个

功能():

function setPartitionNotificationsForDay(passedDate, callback){ 
     var partitionAmt = (bedTimeDate.toDate() - wakeTimeDate.toDate())/surveysInADay; 
     partitionaAmt = Math.round(Math.abs(partitionAmt)); 

     //console.log("Partition amount: " + partitionAmt); 

     didMissNotificationArr = []; 
     notificationTimes = []; 

     var oldMoment = moment(passedDate).hours(wakeTimeDate.hours()).minutes(wakeTimeDate.minutes()); 
     var newMoment = moment(oldMoment).add('milliseconds', partitionAmt); 

     var randMoment; 

     var bufferedOldMoment, bufferedNewMoment; 

     for(var i = 0; i < surveysInADay; i++){ 
      bufferedOldMoment = oldMoment.clone().add('minutes', bufferMins); 
      bufferedNewMoment = newMoment.clone().subtract('minutes', bufferMins) 

      randMoment = randomMoment(bufferedOldMoment, bufferedNewMoment); 

      notificationTimes.push(randMoment); 
      didMissNotificationArr.push(true); 

      oldMoment = newMoment; 
      newMoment = moment(newMoment); 
      newMoment.add('milliseconds', partitionAmt); 
     } 


     if (typeof(callback) === 'function'){ 
      callback(); 
     } 

    } 

//traverse notificationtimes, for all times that are greater than the current time, 
//add notificaitons at those times 
function notificationCheckAndAdd(callback){ 
     var tempMoment; 
     var now = moment(); 

     //console.log("Within notificationCheckAndAdd()"); 
     notificationCount = 0; 
     notificationsToday = 0; 

     for(var i = 0; i < notificationTimes.length; i++){ 
      tempMoment = moment(notificationTimes[i]); 

      if(tempMoment.isAfter(now)){ 
       notificationCount += 1; 
       notificationsToday += 1; 
       //console.log('Should add notification ' + notificationCount + ' at: ' + tempDate.toShortTimeString()); 
       addNotificationAtTime(tempMoment.toDate(), notificationCount); 
       //break; 
      } 
     } 

     //I dont really use the callback function within notificationCheckAndAdd 
     if(typeof(callback) === 'function'){ 
      callback(); 
     } 
    } 

从调试输出:

02-26 19:57:30.702: I/chromium(14683): [INFO:CONSOLE(902)] "WITHIN onDeviceReady()", source: file:///android_asset/www/index.html (902) 
02-26 19:57:30.722: I/chromium(14683): [INFO:CONSOLE(1810)] "Uncaught TypeError: Cannot call method 'toDate' of undefined", source: file:///android_asset/www/index.html (1810) 
02-26 19:57:30.812: I/chromium(14683): [INFO:CONSOLE(1966)] " 
02-26 19:57:30.812: I/chromium(14683): oncancel() has been triggered id: 1", source: file:///android_asset/www/index.html (1966) 

所以,我可以从这个讲的是addNewNotifications()被determineWakeTimeBedTime之前称为()可以完成它的操作,因为determineWakeTimeBedTime()分配变量wakeTimeDate和bedTimeDate,并且它们将是未定义的唯一方法是如果addNewNotifications()开始执行之前执行rmineWakeTimeBedTime()...

如何重构我的代码,以便我可以获得可靠的同步操作?

这是我一直在使用,以更好地理解回调函数的教程: JS Callback tutorial

而且取消后的代码是从addNewNotifications(执行被调用),并记录语句中determineBedtimeWaketime永远不会发生()..所以它看起来好像和我背道而驰。

+0

这个问题太长, – kzahel

回答

2

工作的jsfiddle: http://jsfiddle.net/28Uuj/17/

打开网页检查,并刷新和debugger;语句将打破你进入调试器,所以你可以看到正在发生的事情对每个函数调用。将鼠标悬停在正在调试时传递给每个函数的回调参数上,您会发现这个谜题在你眼前展开! :)

代码本身:

// What you actually want 
// Wrap the function2 call inside an 
// anonymous function, so the interpeter doesn't try to evaluate it right away 
console.log('What you actually want'); 
function1(function(){ function2(function3) }); 
// prints: 
// What you actually want (index):22 
// function1 (index):32 
// function2 (index):39 
// function3 


// The way you have it now 
// The interpreter thinks you want to 
// evaluate function2(function3) and then pass the RETURN value 
// of that into function1 
console.log('The way you have it now'); 
function1(function2(function3)); 
// prints: 
// The way you have it now (index):26 
// function2 (index):39 
// function3 (index):46 
// function1 (index):32 
// Uncaught TypeError: undefined is not a function (index):3 


function function1(callback) 
{ 
    debugger; 
    console.log('function1'); 
    callback(); 
} 

function function2(callback) 
{ 
    debugger; 
    console.log('function2'); 
    callback(); 
} 

function function3() 
{ 
    debugger; 
    console.log('function3'); 
} 
+0

感谢这个! – Gthoma2

+0

@ Gthoma2没问题的人! – SoldierOfFortran