Javascript 在这种情况下,如何避免回调地狱?
正如您所看到的,我有以下代码,函数中的每个函数都依赖于封闭函数的返回值。但问题是,当我继续使用此方法编码时,就会出现回调地狱。如何避免这个地狱Javascript 在这种情况下,如何避免回调地狱?,javascript,node.js,asynchronous,callback,Javascript,Node.js,Asynchronous,Callback,正如您所看到的,我有以下代码,函数中的每个函数都依赖于封闭函数的返回值。但问题是,当我继续使用此方法编码时,就会出现回调地狱。如何避免这个地狱 User.getUserDetail(req.user.id, function(userDetail) { if(req.user.entity_id != '-1') { Entity.getEntityPrimary(req.user.entity_id, function(entityPrimary) {
User.getUserDetail(req.user.id, function(userDetail) {
if(req.user.entity_id != '-1') {
Entity.getEntityPrimary(req.user.entity_id, function(entityPrimary) {
Entity.getEntityPayment(req.user.entity_id, function(entityPayment) {
if(entityPayment.length > 0) {
Entity.subscriptionInfo(entityPayment[0]['date'], entityPayment[0]['exp_date'], function(isSubscribed) {
res.render('capitol', {
user: req.user,
title: 'MCIC',
user_detail: userDetail,
entity_primary: entityPrimary,
entity_payment: entityPayment,
subscriber: true,
is_subscribed: isSubscribed
})
})
} else {
res.render('capitol', {
user: req.user,
title: 'MCIC',
user_detail: userDetail,
entity_primary: entityPrimary,
entity_payment: entityPayment,
subscriber: false
})
}
})
})
} else {
res.render('capitol', {
user: req.user,
title: 'MCIC',
user_detail: userDetail
})
}
})
模型文件如下所示
const MySql = require('../comms/mysql')
const User = module.exports = {}
User.getUserByUsername = function(username, callback) {
MySql.connection.query('SELECT id, username, password, is_active, email, mobile, user_type_id, entity_id FROM `user` WHERE `username` = ?', username, function(err, rows, fields) {
callback(rows)
})
}
User.getUserById = function(id, callback) {
MySql.connection.query('SELECT id, username, password, is_active, email, mobile, user_type_id, entity_id FROM `user` WHERE `id` = ?', id, function(err, rows, fields) {
callback(err, rows)
})
}
User.getUserDetail = function(id, callback) {
MySql.connection.query('SELECT first_name, last_name, dob, address_no, address_street, address_district, address_postal_code, profile_picture, user_id FROM `user_detail` WHERE `user_id` = ?', id, function(err, rows, fields) {
callback(rows)
})
}
我在一个制作网站上使用这段代码。如何轻松地从回调地狱过渡到结构良好的代码?使用JavaScript承诺
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// Do something with value4
});
});
});
});
可以制作
Q.fcall(promisedStep1)
.then(promisedStep2)
.then(promisedStep3)
.then(promisedStep4)
.then(function (value4) {
// Do something with value4
})
.catch(function (error) {
// Handle any error from all above steps
})
阅读此处的更多内容要获得一些快速奖励,您可以将回调函数提取为位于模块级别的命名函数:
// Before: Deeply nested
asyncOperationA(function(resA) {
asyncOperationB(resA, function(resB) {
asyncOperationC(resB, function(resC) {
console.log(resC)
})
})
})
// After: flattened
function handleA(resA) {
asyncOperationB(handleB)
}
function handleB(resB) {
asyncOperationC(handleC)
}
function handleC(resC) {
console.log(resC)
}
asyncOperationA(handleA)
更好的选择是修改代码以使用承诺。使用async/await关键字可以获得最大的可读性。要使用async/await,您需要使用最新的节点版本,或者使用一个transpiler将其转换为普通JavaScript。使用:
我使用这种模式。我使用的是Babel,但是还有其他选项可以获得async Wait支持。我碰巧正在使用PostgreSQL,我的同步查询如下所示:
const results = await db.tx(t => t.batch([query1, query2]));
您可以像这样使用
async/await
删除回调地狱
const Promise = require('bluebird');
const User = Promise.promisifyAll(require('PATH_TO_USER'));
const Entity = Promise.promisifyAll(require('PATH_TO_ENTITY'));
async function yourController(req, res, next) {
try {
const userDetail = await User.getUserDetail(req.user.id);
if(req.user.entity_id !== -1) {
const entityPrimary = await Entity.getEntityPrimary(req.user.entity_id);
const entityPayment = await Entity.getEntityPayment(req.user.entity_id);
if(entityPayment.length > 0) {
const isSubscribed = await Entity.subscriptionInfo(entityPayment[0]['date'], entityPayment[0]['exp_date']);
return res.render('capitol', {
user: req.user,
title: 'MCIC',
user_detail: userDetail,
entity_primary: entityPrimary,
entity_payment: entityPayment,
subscriber: true,
is_subscribed: isSubscribed
})
} else {
return res.render('capitol', {
user: req.user,
title: 'MCIC',
user_detail: userDetail,
entity_primary: entityPrimary,
entity_payment: entityPayment,
subscriber: false
})
}
} else {
return res.render('capitol', {
user: req.user,
title: 'MCIC',
user_detail: userDetail
})
}
} catch(e) {
// handle exception here
}
}
步骤是
- 向控制器添加
关键字,例如async
async函数yourController(req、res、next)
- 使用
bluebird
- 使用
wait
Q
库,普通的javascriptPromise
就足够了。
const Promise = require('bluebird');
const User = Promise.promisifyAll(require('PATH_TO_USER'));
const Entity = Promise.promisifyAll(require('PATH_TO_ENTITY'));
async function yourController(req, res, next) {
try {
const userDetail = await User.getUserDetail(req.user.id);
if(req.user.entity_id !== -1) {
const entityPrimary = await Entity.getEntityPrimary(req.user.entity_id);
const entityPayment = await Entity.getEntityPayment(req.user.entity_id);
if(entityPayment.length > 0) {
const isSubscribed = await Entity.subscriptionInfo(entityPayment[0]['date'], entityPayment[0]['exp_date']);
return res.render('capitol', {
user: req.user,
title: 'MCIC',
user_detail: userDetail,
entity_primary: entityPrimary,
entity_payment: entityPayment,
subscriber: true,
is_subscribed: isSubscribed
})
} else {
return res.render('capitol', {
user: req.user,
title: 'MCIC',
user_detail: userDetail,
entity_primary: entityPrimary,
entity_payment: entityPayment,
subscriber: false
})
}
} else {
return res.render('capitol', {
user: req.user,
title: 'MCIC',
user_detail: userDetail
})
}
} catch(e) {
// handle exception here
}
}