2016-01-08 223 views
0

我想通過node.js中的JS Promises來工作,並且沒有獲得在不同函數之間傳遞promise的解決方案。JS承諾在函數之間傳遞/等待承諾

任務

對於主要的邏輯,我需要從一個REST API獲取的項目 JSON對象。 API處理本身位於api.js文件中。

對API的請求通過request-promise模塊進行。我有一個私人的makeRequest函數和公共幫助函數,如API.getItems()

index.js中的主邏輯需要等待API函數,直到它可以執行。

問題

  1. 的承諾傳球樣的作品,但我不知道這是不是一個巧合。返回一個Promise返回makeRequest中的響應是否正確?
  2. 我是否真的需要所有的承諾才能使主邏輯工作,只有等待項目設置後?有一種更簡單的方法嗎?
  3. 我仍然需要弄清楚,如何最好地處理a)makeRequest和b)getItems函數的錯誤。對於承諾的最佳做法是什麼?傳遞錯誤對象?

這裏是我想出了現在的代碼: 起初我開始做與API請求:

// ./lib/api.js 

var request = require('request-promise'); 

// constructor 
var API = function() { 
    var api = this; 

    api.endpoint = "https://api.example.com/v1"; 
    //... 
}; 

API.prototype.getItems = function() { 
    var api  = this; 
    var endpoint = '/items'; 


    return new Promise(function (resolve, reject) { 
    var request = makeRequest(api, endpoint).then(function (response) { 
     if (200 === response.statusCode) { 
     resolve(response.body.items); 
     } 
    }, function (err) { 
     reject(false); 
    }); 
    }); 
}; 

function makeRequest(api, endpoint) { 
    var url  = api.endpoint + endpoint; 
    var options = { 
    method: 'GET', 
    uri: url, 
    body: {}, 
    headers: {}, 
    simple: false, 
    resolveWithFullResponse: true, 
    json: true 
    }; 

    return request(options) 
    .then(function (response) { 
     console.log(response.body); 
     return response; 
    }) 
    .catch(function (err) { 
     return Error(err); 
    }); 
} 

module.exports = new API(); 

一些更多的背景

// index.js 

var API = require('./lib/api'); 

var items; 

function mainLogic() { 

    if (items instanceof Error) { 
    console.log("No items present. Stopping main logic."); 
    return; 
    } 

    // ... do something with items 
} 


API.getItems().then(function (response) { 
    if (response) { 
    console.log(response); 
    items = response; 
    mainLogic(); 
    } 
}, function (err) { 
    console.log(err); 
}); 

api.js request模塊,與回調一起工作。由於這些被稱爲異步,項目從來沒有把它放在主邏輯上,我用Promise處理它。

+2

在這裏,還有一個在'新的承諾'中包裝了現有的承諾[這是一種反模式](http://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-怎麼辦,我避免的,它)。你可以從'makeRequest'返回request(options)','getItems'返回makeRequest(api,endpoint)',最後看起來'mainLogic()'應該調用'getItems'而不是其他方法 – CodingIntrigue

回答

4

你在這裏失蹤兩件事情:

  1. ,你可以鏈的承諾直接與
  2. 的方式承諾,錯誤處理工作。

您可以makeRequest()改變return語句:

return request(options); 

由於makeRequest()回報的承諾,你可以在getItems()重複使用它,你不必明確創建一個新的承諾。該.then()功能已經可以實現這個要求:

return makeRequest(api, endpoint) 
    .then(function (response) { 
     if (200 === response.statusCode) { 
      return response.body.items; 
     } 
     else { 
      // throw an exception or call Promise.reject() with a proper error 
     } 
    }); 

如果makeRequest()返回的承諾遭到拒絕,你不處理拒絕 - 就像在上面的代碼 - 由.then()返回的承諾也將被拒絕。您可以將行爲與異常進行比較。如果你沒有捕捉到它,它就會讓這個callstack起泡。

最後,在index.js你應該使用getItems()這樣的:

API.getItems().then(function (response) { 
    // Here you are sure that everything worked. No additional checks required. 
    // Whatever you want to do with the response, do it here. 
    // Don't assign response to another variable outside of this scope. 
    // If processing the response is complex, rather pass it to another 
    // function directly. 
}, function (err) { 
    // handle the error 
}); 

我推薦這個博客帖子,以更好地瞭解承諾的概念:你創造了太多的承諾

https://blog.domenic.me/youre-missing-the-point-of-promises/

+0

謝謝你的回覆。這真的幫助我更好地理解Promise。根據你的回答,現在一切正常,但是錯誤不能從'makeRequest'正確地傳遞給'API.getItems()。then'函數。我現在就處理這件事。 – Cino