2015-10-20 48 views
1

假設我有3個文件。如何處理Node.js中的回調?

index.js撥打電話時這樣

$.post('/test/', data, function(response) { 
//handle success here 
}) 

routes.js後端處理這樣

app.post('/test/', function(req, res){ 
    item.getItems(function(response){ 
    res.json(response); 
    }); 
}); 

items.js的路徑是訪問數據庫,使一個模型每個項目的POST請求

function getItems(callback) { 
    database.query('SELECT * from items', function(result){ 
    result.forEach(function(item){ 
     request.post('/api/', item, function(req, res) { 
      //finished posting item 
     }); 
    }); 
    }); 
    //callback here doesnt wait for calls to finish 
} 

其中/何時應該調用傳遞給getItems()的回調以處理index.js中的成功/失敗?

回答

2

因爲你request.post()操作是異步,您必須使用跟蹤時,他們都做的一些方法,然後你可以調用你的回調。有多種方式可以做到這一點。我將概述幾點:

手動保持請求操作的計數的軌道

function getItems(callback) { 
    database.query('SELECT * from items', function(result){ 
    var remaining = result.length; 
    result.forEach(function(item){ 
     request.post('/api/', item, function(err, res) { 
      --remaining; 
      //finished posting item 
      if (remaining === 0) { 
       callback(); 
      } 
     }); 
    }); 
    }); 
} 

與手動這樣做的主要問題是,傳播嵌套異步操作的錯誤是很難當你真正弄清楚你將如何處理錯誤。這在這裏顯示的其他方法中更容易。

使用承諾

// load Bluebird promise library 
var Promise = require('bluebird'); 

// promisify async operations 
Promise.promisifyAll(request); 

function queryAsync(query) { 
    return new Promise(function(resolve, reject) { 
     // this needs proper error handling from the database query 
     database.query('SELECT * from items', function(result){ 
      resolve(result); 
     }); 
    }); 
} 

function getItems(callback) { 
    return queryAsync('SELECT * from items').then(function(result) { 
     return Promise.map(result, function(item) { 
      return request.postAsync('/api/', item); 
     }); 
    }); 
} 

getItems.then(function(results) { 
    // success here 
}, function(err) { 
    // error here 
}) 
+0

@JackJohnson - 爲你做了這項工作? – jfriend00

+0

我還沒有試過,明天我會試試看第一件事。謝謝。 –

+0

@ jfriend00,我很想知道'諾言'。map'排成一行** //錯誤在這裏** getItems'的一部分...讓我們假設你有20個項目用於'postAsync',其中15個成功,5個失敗......將15個結果放在'results'中爲了成功和5在錯誤中的錯誤?我對承諾有什麼高層次的理解,但我還沒有看到一個承諾數組的例子。 – incutonez

1

在服務器端代碼中發出API請求似乎很奇怪,除非這是某種與API交互的中間層代碼......但是您正在與數據庫交互,所以我對於爲什麼你不能只是做一個數據庫插入,或者有一個批量插入API調用,仍然困惑不解?

無論如何,如果你必須按照你所要求的方式來做,我過去用一個遞歸的方法來完成結果數組...我真的不知道這是否是一個好東西方法,所以我想聽聽任何反饋。事情是這樣的:

function recursiveResult(result, successfulResults, callback) { 
    var item = result.shift(); 
    // if item is undefined, then we've hit the end of the array, so we'll call the original callback 
    if (item !== undefined) { 
    console.log(item, result); 
    // do the POST in here, and in its callback, call recursiveResult(result, successfulResults, callback); 
    successfulResults.push(item); 
    return recursiveResult(result, successfulResults, callback); 
    } 
    // make sure callback is defined, otherwise, server will crash 
    else if (callback) { 
    return callback(successfulResults); 
    } 
    else { 
    // log error... callback undefined 
    } 
} 

function getItems(callback) { 
    var successfulResults = []; 
    var result = [1, 2, 3, 4]; 
    recursiveResult(result, successfulResults, callback); 
} 

console.log('starting'); 
getItems(function(finalResult) { 
    console.log('done', finalResult); 
}); 
+0

謝謝,只是需要在服務器端的API請求,以更新另一臺服務器上的項目。儘管有點複雜,但看起來這是一個不錯的選擇。如果沒有其他更簡單的解決方案,我可能只是去解決這個問題。我的另一個想法是在函數之後使用lodash,並在那裏調用回調函數。 –

+0

啊,好吧,那正是我所想的。你不能進行批量API調用嗎?如果你已經抽象出了你的單個POST的邏輯,那麼製作批量插入方法會非常容易。我同意這有點複雜,起初很混亂,但似乎爲我完成了這項工作。 – incutonez

+0

你能解釋批量API調用的含義嗎? –