比如现在有一个情景,就是传入一个token,根据这个token请求一次网络,然后获取用户ID,讲获取的用户ID访问数据库,获取用户信息,讲用户信息和ID一起写入到一个文本中去,在这样的一个流程中,传统的是需要这样的。
request(token)
.then(function(id) {
mongodb
.find(id).toArray()
.then(function(info){
fs.writeFile(filename, info+id)
.then(function(){console.log('success');}
})
})
但是如果按照这样的话,如果需求要多的话,似乎又掉入了回调地狱,那么有什么问题可以解决这个问题呢?就是后面的异步操作都需要前面异步操作的值,或者自定义的值?
用链式调用写法,第一个 then 的返回值是第二个 then 的参数。
刚才在手机上回复的,没法敲代码。简单来说,你的例子可以改成这样:
let tokenId, filename = 'xxx'
request(token).then(id => {
tokenId = id
return mongodb.find(id).toArray()
}).then(info => {
return fs.writeFile(filename, `${info}${tokenId}`)
}).then(() => {
console.log('success')
})
每个 then 里面需要共享的变量只能放到 then 外面去定义了。
模拟查询方法
var request = function (token) {
return new Promise((resolve, reject)=> {
setTimeout(
()=> {
token ? resolve(2) : reject('token error');
},
1000
)
});
};
var find = function (id) {
return new Promise((resolve, reject)=> {
setTimeout(
()=> {
id ? resolve(id + '-info') : reject('id error');
},
1000
)
});
};
Promise
一般来说promise的链式调用时这样的
request('token')
.then(function (id) {
return find(id);
})
.then(function (info) {
console.log( info);
});
像楼主所说的情况需要记录id,所以改成如下
var data = {};
request('token')
.then(function (id) {
data.id = id;
return find(id);
})
.then(function (info) {
console.log(data.id, info);
});
很不优雅。Promise的缺点就是链过长以后分不清业务到底干了写啥,满屏幕的then。
Generator
ES有个新特性叫Generator,结合TJ大神的 co,可以将代码写成如下
co(function *() {
var id = yield request('token');
var info = yield find(id);
console.log(id, info);
});
看起来舒服多了,但是毕竟还是用到了第三方的库
async
ES7的提案,代码写法如下
(async function () {
var id = await request('token');
var info = await find(id);
console.log(id, info);
})();
新特性需要babel转码。 以上就是我所了解的。
@darkbaby123 我主要是不想共享变量到外面去😷 自豪地采用 CNodeJS ionic
@yuyang041060120 那我试一下co库 自豪地采用 CNodeJS ionic
var Promise2 = require('bluebird');
request(token).then(id => Promise2.all([ id, mongodb.find(id).toArray() ]).spread((id, info) => here);
@XGHeaven 我想不太适用你的场景吧,你可以试一下。。。