寻找node.js的承诺蓝鸟代码审查
Look for Promise bluebird code review for node.js
何时何地需要使用new Promise(Function<Function resolve, Function reject> resolver) -> Promise
userInfo.js
var Promise = require('bluebird');
var winston = require('winston');
var _ = require('lodash');
var request = Promise.promisify(require("request"));
exports.getWeather = function (data) {
var cityName = data.userProfile.city;
return request("http://0.0.0.0:3003/api/Weather/byCity?city=" + cityName).spread(function (res, body) {
var result = JSON.parse(body).data;
return _.merge(data, result);
});
};
exports.getUserProfile = function (userId) {
return new Promise(function (resolve, reject) {
request("http://0.0.0.0:3003/api/UserProfile/getUserProfile?id=" + userId).spread(function (res, body) {
var result = JSON.parse(body).data;
resolve(result);
});
})
};
exports.getEvents = function (data) {
var cityName = data.userProfile.city;
return request("http://0.0.0.0:3003/api/Events/byCity?city=" + cityName).spread(function (res, body) {
var result = JSON.parse(body).data;
return _.merge(data, result);
});
};
exports.getFashion = function (data) {
var gender = data.userProfile.gender;
return request("http://0.0.0.0:3003/api/Fashion/byGender?gender=" + gender).spread(function (res, body) {
var result = JSON.parse(body).data;
return _.merge(data, result);
});
};
exports.displayDetail = function (data) {
console.log(data);
};
在上面的代码中,我尝试用2种方式调用promise
getUserProfile.js
var userInfo = require('./userInfo');
module.exports = function(){
return userInfo.getUserProfile(3)
.then(userInfo.getFashion)
.then(userInfo.getEvents)
.then(userInfo.getWeather)
.then(userInfo.displayDetail)
.catch(function (e) {
console.log('Error:');
console.error(e.stack)
})
.finally(function () {
console.log('done');
});
}
方式2:
getUserInformation.js
var userInfo = require('./userInfo');
module.exports = function () {
return new Promise(function (resolve, reject) {
resolve(3);
})
.then(userInfo.getUserProfile)
.then(userInfo.getFashion)
.then(userInfo.getEvents)
.then(userInfo.getWeather)
.then(userInfo.displayDetail)
.catch(function (e) {
console.log('Error:');
console.error(e.stack)
})
.finally(function () {
console.log('done');
});
};
getDetails.js
var userInfo = require('./getUserInformation');
userInfo()
.then(function(){
console.log('getDetails done')
})
.catch(function (e) {
console.log('Error:');
console.error(e.stack)
})
.finally(function () {
console.log('done');
});
请让我知道使用这些方式有什么不同,有没有什么问题?
exports.getUserProfile = function (userId) { return new Promise(function (resolve, reject) { request("http://0.0.0.0:3003/api/UserProfile/getUserProfile?id=" + userId).spread(function (res, body) { var result = JSON.parse(body).data; resolve(result); }); }) };
请不要这样做。从回调中取出return
,并返回由then
创建的承诺,就像您在其他三个方法中所做的那样。
return userInfo.getUserProfile(3) .then(…)
与
return new Promise(function (resolve, reject) { resolve(3); }) .then(userInfo.getUserProfile) .then(…)
嗯,第一个更容易读,更简洁。它们几乎是等价的,除了getUserProfile
确实同步抛出,这本来就不应该。同样在第一种情况下,getUserProfile
作为 userInfo
的方法被调用,而在第二种情况下,它只是一个回调函数,调用中的this
将是不同的。
Promise.resolve
而不是new Promise
构造函数来极大地简化:
return Promise.resolve(3)
.then(userInfo.getUserProfile)
.then(…)
这完全没问题,并且与链的其余部分更好地对齐。说到这,……
.then(userInfo.getFashion) .then(userInfo.getEvents) .then(userInfo.getWeather)
,其中每个函数返回一个承诺,该承诺解析为附加数据合并到参数
并不是解决这个问题的最佳方法。是的,它确保了这三个函数是依次调用的,并且在这种情况下是一种可接受的模式。然而,在你的情况下,你混合request
调用API与参数提取和结果合并在同一函数;通过关注点分离,你不应该。让函数变成纯函数
exports.… = function (arg) {
return request("http://0.0.0.0:3003/api/…?…=" + arg).spread(function (res, body) {
return JSON.parse(body).data;
});
};
现在你可以分别组合它们——不仅按顺序,而且并行:
userInfo.getUserProfile(3)
.then(function(data) {
var p = data.userProfile;
return Promise.prop({
userProfile: 0,
fashion: userInfo.getFashion(p.gender), // `'
events: userInfo.getEvents(p.city), // }=> execute requests in parallel
weather: userInfo.getWeather(p.city) // ./
});
})
.then(userInfo.displayDetail)
.catch(function (e) {
console.error('Error:', e.stack)
});
第一种方法更具可读性,并且与第二种方法一样,使用返回常量的承诺开始链没有任何好处。
它们都有效地做同样的事情,但有一点需要注意:在第二个示例中(用Promise启动链),getUserProfile
调用将在下一个tick上运行(类似于在setTimeout 0中抛出它),而不是自动运行。
- 在蓝鸟中处理异常
- 而循环使用蓝鸟承诺
- 蓝鸟承诺并抓住树枝
- 蓝鸟的done()和spread()之间的区别
- 蓝鸟承诺的困难.bind()
- 蓝鸟没有正确解决承诺
- 将异步工作流更改为承诺(蓝鸟)
- 蓝鸟承诺 - 嵌套与拒绝模式
- 蓝鸟承诺循环
- Promise.每个在蓝鸟都有某种所有操作完成的回调吗?
- 创建具有蓝鸟承诺的节流功能
- 蓝鸟递归承诺未得到解决/实现
- 蓝鸟与猫鼬,类型错误:.create(..).然后(..).Nodeify不是一个函数
- 蓝鸟中未经处理的拒绝
- 有前途的已经承诺的图书馆与蓝鸟
- 停止蓝鸟承诺中的错误传播
- 蓝鸟承诺和领域
- 连锁承诺(蓝鸟)
- 寻找node.js的承诺蓝鸟代码审查
- 将承诺代码从Q转换为蓝鸟