Javascript 承诺基础。如何推荐异步节点代码?
我从承诺开始,并尝试使用它们而不是回调来避免回调地狱。异步函数是来自MongoDB、Redis、bcrypt模块等的函数的混合体。我能够做到这一点:Javascript 承诺基础。如何推荐异步节点代码?,javascript,node.js,asynchronous,promise,q,Javascript,Node.js,Asynchronous,Promise,Q,我从承诺开始,并尝试使用它们而不是回调来避免回调地狱。异步函数是来自MongoDB、Redis、bcrypt模块等的函数的混合体。我能够做到这一点: var insert = Q.denodify(db.collection(USERS).insert); var createCollection = Q.denodify(db.createCollection); var sadd = Q.denodify(redisClient.sadd); var sismember = Q.denodi
var insert = Q.denodify(db.collection(USERS).insert);
var createCollection = Q.denodify(db.createCollection);
var sadd = Q.denodify(redisClient.sadd);
var sismember = Q.denodify(redisClient.sismember);
var genSalt = Q.denodify(bcrypt.genSalt);
var hash = Q.denodify(bcrypt.hash);
// SANITY CHECK
// a "name" parameter is required
if(!req.body.name || !isValidName(req.body.name))
return next(get400InvalidNameError());
// SANITY CHECK
// a "key" is optional
// if one is supplied, it must be valid
// this key will be hashed later
if(req.body.key){
if(!isValidKey(req.body.key))
return next(get400InvalidKeyError());
}
// STEPS:
// 1.
// check Redis cache to see if the "name" is already taken
// if yes, return error. if no, continue
// 2.
// construct a "user" object with name = req.body.name
// 3.
// req.body.key provided?
// if yes, generate salt and hash the key. Set user.key = hash
// if not, continue
// 4.
// create a collection in MongoDB with the same name as req.body.name
// 5.
// add req.body.name to cache
// 6.
// send a response to user using res.json() / res.end()
sismember(USERS,req.body.name)
.then(createUserObj,errHandler)
.then(genSalt(10),errHandler)
.then(hash(req.body.key,salt))
.then(createCollection(req.body.name),errHandler)
.then(sadd(USERS,req.body.name),errHandler)
.then(insert(user),errHandler)
.then(get200UserCreated,errHandler)
让我困惑的是最后一部分,所有这些函数都是then()
-ed在一起的。我有几个问题:1.如何将一个异步函数的结果提供给另一个?
2.如何有条件地决定执行哪些函数?例如,我只想在提供了
req.body.key
时生成salt和hash
3.我的then()
顺序正确吗
var myprom = Promise.resolve(1) // the simplest promise way
这里,如果我们用链接,那么
参数将等于1
myprom.then(function( val ){
console.log(val); // 1
return 33;
}).then(function(passed){
console.log(passed) // 33
return 44;
}).then(function(other){
console.log(other) // 44
if( other > 44 ){
return 'AAA';
} else {
return 'BBB';
}
}).then(function(res){
console.log(res) // BBB
})
这里的重要的是你从你的承诺中得到回报。现在是异步。第部分:
// we can also instanciate a new Promise object
var myprom = new Promise(function(resolve , reject){
console.log('we start here');
setTimeout(function(){
console.log('we continue here');
resolve( 'time out' );
} , 2000);
}).then(function( val ){
console.log('and we end here : ' + val);
});
第二部分,然后在第一部分中调用resolve
。
所以我们总是等到最后,这是承诺的“魔力”
传递给resolve的参数将成为下一个的参数,然后
这与我们关于返回的第一个示例相同
它非常重要
当您这样做时:
sismember(USERS,req.body.name)
这与超时的原理相同
var sismember = function(USERS , req.body.name){
var promiseToReturn = new Promise(function(resolve,reject){
var result = ''; // <---do something with USERS and req.body.name
// and if it is ok
if(result){
resolve( result )
} else {// if it is not ok
reject( result )
}
});
return promiseToReturn; // <-- we can chain with then
})
.then(createUserObj,errHandler)
如何有条件地决定执行哪些函数?例如,我只想在提供req.body.key时生成salt和hash
不同的方法
我的then()序列正确吗
不强>
你不能像那样调用函数
.then(genSalt(10),errHandler) // <-- you are invoking the result not the function
// you are doing something like that:
.then('Adekj34LLKDF' , errHandler)
但是promise-chain提供了prev函数中的参数,您不必提供它
见上面的例子
解决此问题后,在末尾添加一个catch来处理可能发生的任何错误。
本部分:
.then(get200UserCreated,errHandler)//<--- errHandler for prev then
.then(insert(user),errHandler)
如果在insert(user)
过程中发生错误,将由下一个错误处理程序或catch处理
sismember(USERS,req.body.name)
.then(createUserObj,errHandler)// <-- errHandler for : sismember
.then(genSalt(10),errHandler)// <-- errHandler for : createUserObj
.then(hash(req.body.key,salt))// <-- missing errHandler for : genSalt
.then(createCollection(req.body.name),errHandler)// <-- errHandler for : hash
.then(sadd(USERS,req.body.name),errHandler)// <-- errHandler for createCollection
.then(insert(user),errHandler)// <-- errHandler for :
.then(get200UserCreated,errHandler)// <-- errHandler for : insert
.catch(errHandler)// <-- errHandler for : get200UserCreated
sismember(用户,请求主体名称)
.然后(createUserObj,errHandler)//
如何将一个异步函数的结果提供给另一个异步函数
当你使用承诺时,你可以解决或拒绝它
var myprom = Promise.resolve(1) // the simplest promise way
这里,如果我们用链接,那么
参数将等于1
myprom.then(function( val ){
console.log(val); // 1
return 33;
}).then(function(passed){
console.log(passed) // 33
return 44;
}).then(function(other){
console.log(other) // 44
if( other > 44 ){
return 'AAA';
} else {
return 'BBB';
}
}).then(function(res){
console.log(res) // BBB
})
这里的重要的是你从你的承诺中得到回报。
现在是异步。第部分:
// we can also instanciate a new Promise object
var myprom = new Promise(function(resolve , reject){
console.log('we start here');
setTimeout(function(){
console.log('we continue here');
resolve( 'time out' );
} , 2000);
}).then(function( val ){
console.log('and we end here : ' + val);
});
第二部分,然后在第一部分中调用resolve
。
所以我们总是等到最后,这是承诺的“魔力”
传递给resolve的参数将成为下一个的参数,然后
这与我们关于返回的第一个示例相同
它非常重要
当您这样做时:
sismember(USERS,req.body.name)
这与超时的原理相同
var sismember = function(USERS , req.body.name){
var promiseToReturn = new Promise(function(resolve,reject){
var result = ''; // <---do something with USERS and req.body.name
// and if it is ok
if(result){
resolve( result )
} else {// if it is not ok
reject( result )
}
});
return promiseToReturn; // <-- we can chain with then
})
.then(createUserObj,errHandler)
如何有条件地决定执行哪些函数?例如,我只想在提供req.body.key时生成salt和hash
不同的方法
我的then()序列正确吗
不强>
你不能像那样调用函数
.then(genSalt(10),errHandler) // <-- you are invoking the result not the function
// you are doing something like that:
.then('Adekj34LLKDF' , errHandler)
但是promise-chain提供了prev函数中的参数,您不必提供它
见上面的例子
解决此问题后,在末尾添加一个catch来处理可能发生的任何错误。
本部分:
.then(get200UserCreated,errHandler)//<--- errHandler for prev then
.then(insert(user),errHandler)
如果在insert(user)
过程中发生错误,将由下一个错误处理程序或catch处理
sismember(USERS,req.body.name)
.then(createUserObj,errHandler)// <-- errHandler for : sismember
.then(genSalt(10),errHandler)// <-- errHandler for : createUserObj
.then(hash(req.body.key,salt))// <-- missing errHandler for : genSalt
.then(createCollection(req.body.name),errHandler)// <-- errHandler for : hash
.then(sadd(USERS,req.body.name),errHandler)// <-- errHandler for createCollection
.then(insert(user),errHandler)// <-- errHandler for :
.then(get200UserCreated,errHandler)// <-- errHandler for : insert
.catch(errHandler)// <-- errHandler for : get200UserCreated
sismember(用户,请求主体名称)
.然后(createUserObj,errHandler)//
如何将一个异步函数的结果提供给另一个异步函数
当你使用承诺时,你可以解决或拒绝它
var myprom = Promise.resolve(1) // the simplest promise way
这里,如果我们用链接,那么
参数将等于1
myprom.then(function( val ){
console.log(val); // 1
return 33;
}).then(function(passed){
console.log(passed) // 33
return 44;
}).then(function(other){
console.log(other) // 44
if( other > 44 ){
return 'AAA';
} else {
return 'BBB';
}
}).then(function(res){
console.log(res) // BBB
})
这里的重要的是你从你的承诺中得到回报。
现在是异步。第部分:
// we can also instanciate a new Promise object
var myprom = new Promise(function(resolve , reject){
console.log('we start here');
setTimeout(function(){
console.log('we continue here');
resolve( 'time out' );
} , 2000);
}).then(function( val ){
console.log('and we end here : ' + val);
});
第二部分,然后在第一部分中调用resolve
。
所以我们总是等到最后,这是承诺的“魔力”
传递给resolve的参数将成为下一个的参数,然后
这与我们关于返回的第一个示例相同
它非常重要
当您这样做时:
sismember(USERS,req.body.name)
这与超时的原理相同
var sismember = function(USERS , req.body.name){
var promiseToReturn = new Promise(function(resolve,reject){
var result = ''; // <---do something with USERS and req.body.name
// and if it is ok
if(result){
resolve( result )
} else {// if it is not ok
reject( result )
}
});
return promiseToReturn; // <-- we can chain with then
})
.then(createUserObj,errHandler)
如何有条件地决定执行哪些函数?例如,我只想在提供req.body.key时生成salt和hash
不同的方法
我的then()序列正确吗
不强>
你不能像那样调用函数
.then(genSalt(10),errHandler) // <-- you are invoking the result not the function
// you are doing something like that:
.then('Adekj34LLKDF' , errHandler)
但是promise-chain提供了prev函数中的参数,您不必提供它
见上面的例子
解决此问题后,在末尾添加一个catch来处理可能发生的任何错误。
本部分:
.then(get200UserCreated,errHandler)//<--- errHandler for prev then
.then(insert(user),errHandler)
如果在insert(user)
过程中发生错误,将由下一个错误处理程序或catch处理
sismember(USERS,req.body.name)
.then(createUserObj,errHandler)// <-- errHandler for : sismember
.then(genSalt(10),errHandler)// <-- errHandler for : createUserObj
.then(hash(req.body.key,salt))// <-- missing errHandler for : genSalt
.then(createCollection(req.body.name),errHandler)// <-- errHandler for : hash
.then(sadd(USERS,req.body.name),errHandler)// <-- errHandler for createCollection
.then(insert(user),errHandler)// <-- errHandler for :
.then(get200UserCreated,errHandler)// <-- errHandler for : insert
.catch(errHandler)// <-- errHandler for : get200UserCreated
sismember(用户,请求主体名称)
.然后(createUserObj,errHandler)//
如何将一个异步函数的结果提供给另一个异步函数
当你使用承诺时,你可以解决或拒绝它
var myprom = Promise.resolve(1) // the simplest promise way
这里,如果我们用链接,那么
参数将等于1
myprom.then(function( val ){
console.log(val); // 1
return 33;
}).then(function(passed){
console.log(passed) // 33
return 44;
}).then(function(other){
console.log(other) // 44
if( other > 44 ){
return 'AAA';
} else {
return 'BBB';
}
}).then(function(res){
console.log(res) // BBB
})
这里的重要的是你从你的承诺中得到回报。
现在是异步。第部分:
// we can also instanciate a new Promise object
var myprom = new Promise(function(resolve , reject){
console.log('we start here');
setTimeout(function(){
console.log('we continue here');
resolve( 'time out' );
} , 2000);
}).then(function( val ){
console.log('and we end here : ' + val);
});
第二部分,然后在第一部分中调用resolve
。
所以我们总是等到最后,这是承诺的“魔力”
传递给resolve的参数将成为下一个的参数,然后