2015-05-19 23 views
0

我需要在我的代碼中使用藍鳥,我不知道如何使用它。我的代碼包含嵌套循環。當用戶登錄時,我的代碼將運行。它將開始查找用戶下的任何文件,如果有文件,則它將循環以獲取文件的名稱,因爲該名稱存儲在字典中。一旦獲得了名稱,它就會將該名稱存儲在數組中。一旦存儲了所有的名字,它就會在res.render()中傳遞。如何在嵌套for循環中使用promise藍鳥?

這裏是我的代碼:

router.post('/login', function(req, res){ 
    var username = req.body.username; 
    var password = req.body.password; 
    Parse.User.logIn(username, password, { 
    success: function(user){ 
     var Files = Parse.Object.extend("File"); 
     var object = []; 
     var query = new Parse.Query(Files); 
     query.equalTo("user", Parse.User.current()); 
     var temp; 
     query.find({ 
     success:function(results){ 
      for(var i=0; i< results.length; i++){ 
      var file = results[i].toJSON(); 
      for(var k in file){ 
       if (k ==="javaFile"){ 
       for(var t in file[k]){ 
       if (t === "name"){ 
        temp = file[k][t]; 
        var getname = temp.split("-").pop(); 
        object[i] = getname; 
       } 
       } 
      } 
      } 
     } 
     } 
    }); 
     console.log(object); 
     res.render('filename', {title: 'File Name', FIles: object}); 
     console.log(object); 
    }, 
    error: function(user, error) { 
     console.log("Invalid username/password"); 
     res.render('logins'); 
    } 
    }) 
}); 

編輯:代碼不起作用,因爲在第一和第二的console.log(對象),我得到一個空數組。我想獲得一個項目,因爲我有一個文件保存

+1

爲什麼你需要使用藍鳥?如果將'res.render'移動到最裏面的'success'回調末尾,您的代碼應該已經工作了 –

+0

代碼不起作用,因爲在第一個和第二個console.log(對象)上,我得到一個空陣列。我想獲得該數組中的一個項目,因爲我保存了一個文件。 – Suji

回答

1

JavaScript代碼是從上到下全部解析的,但它不一定按異步代碼的順序執行。問題在於,在登錄函數的成功回調中有日誌語句,但是在查詢的成功回調中它是而不是

您有幾種選擇:

  1. 移動的console.log報表內成功回調的內部,雖然他們可以在加載時被解析,他們不執行,直到兩個回調已經調用。
  2. Promisify傳統上依賴和調用回調函數的函數,然後將處理程序從返回的值中掛起以將承諾鏈接在一起。

第一個選項根本不使用承諾,而僅僅依靠回調。爲了扁平化你的代碼,你需要提交這些函數並鏈接它們。

我不熟悉你在那裏使用的成功和錯誤回調的語法,也不熟悉Parse。通常,你會做這樣的事情:

query.find(someArgsHere, function(success, err) { 
}); 

但你必須巢裏面另一個回調,而這裏面另一個回調。爲了「扁平」金字塔,我們讓函數返回一個承諾,然後我們可以鏈接承諾。假設Parse.User.logIn是一個回調式函數(就像Parse.Query一樣。找到),你可能會做這樣的事情:

var Promise = require('bluebird'); 
var login = Promise.promisify(Parse.User.logIn); 
var find = Promise.promisify(Parse.Query.find); 
var outerOutput = []; 

return login(yourArgsHere) 
    .then(function(user) { 
    return find(user.someValue); 
    }) 
    .then(function(results) { 
    var innerOutput = []; 
    // do something with innerOutput or outerOutput and render it 
    }); 

這應該很熟悉,你可以用來同步碼,除了沒有保存返回值到一個變量,然後通過該變量你的下一個函數調用,你使用「then」處理程序將承諾鏈接在一起。您可以在第二個處理程序中創建整個輸出變量,或者您可以在啓動該承諾鏈之前聲明變量輸出,然後它將處於所有這些函數的範圍內。我已經向您展示了上述兩個選項,但顯然您不需要定義這兩個變量並將它們賦值。只需選擇適合您需求的選項即可。

您也可以使用Bluebird的promisifyAll()函數來封裝具有等效promise返回函數的整個庫。它們都將具有與Async後綴相同的函數名稱。因此,假設解析庫包含名爲someFunctionName()和someOtherFunc回調風格的函數(),你可以這樣做:

var Parse = Promise.promisifyAll(require("Parse")); 
var promiseyFunction = function() { 
    return Parse.someFunctionNameAsync() 
    .then(function(result) { 
     return Parse.someOtherFuncAsync(result.someProperty); 
    }) 
    .then(function(otherFuncResult) { 
     var something; 
     // do stuff to assign a value to something 
     return something; 
    }); 
} 
0

我有幾個指針。 ...順便說一句,你想使用Parse的諾言嗎?

可以擺脫那些內嵌套循環和一些其他的變化:

使用一些語法這樣更優雅:

/// You could use a map function like this to get the files into an array of just thier names 
var fileNames = matchedFiles.map(function _getJavaFile(item) { 
    return item && item.javaFile && item.javaFile.name // NOT NULL 
     && item.javaFile.name.split('-')[0]; // RETURN first part of name 
}); 


// Example to filter/retrieve only valid file objs (with dashes in name) 
var matchedFiles = results.filter(function _hasJavaFile(item) { 
    return item && item.javaFile && item.javaFile.name // NOT NULL 
     && item.javaFile.name.indexOf('-') > -1; // and has a dash 
}); 

這裏是使用解析的原生承諾的例子(以上代碼添加到下面行4/5,音符',那麼()函數,這是有效的,現在你的「回調」處理器):

var GameScore = Parse.Object.extend("GameScore"); 
var query = new Parse.Query(GameScore); 
query.select("score", "playerName"); 
query.find().then(function(results) { 
    // each of results will only have the selected fields available. 
}); 
+0

你的代碼也一口氣做了太多不同的動作。我會用更多的代碼編輯我的答案... –