使用本机 Promises 执行此操作。了解一下胆量是件好事。
这里被称为“Promise Constructor Antipattern”,正如@Bergi 在 cmets 中指出的那样。不要这样做。看看下面更好的方法。
var contextA = new Promise(function(resolve, reject) {
request('http://someurl.com', function(err, response, body) {
if(err) reject(err);
else {
resolve(body.toJSON());
}
});
});
var contextB = new Promise(function(resolve, reject) {
request('http://contextB.com', function(err, response, contextB) {
if(err) reject(err);
else {
contextA.then(function(contextA) {
res.render('page', contextA, contextB);
});
}
});
});
这里的绝妙技巧,我认为通过使用原始承诺,您会意识到这一点,contextA 解析一次,然后我们就可以访问它的解析结果。也就是说,我们从不向someurl.com 发出上述请求,但仍然可以访问contextA 的JSON。
所以我可以想象创建一个contextC 并重用 JSON,而无需发出另一个请求。 Promises 总是只解析一次。您必须取出匿名 executor 函数并将其放入 new Promise 以刷新该数据。
注意事项:
这将并行执行contextA 和contextB,但当A 和B 都被解析时,将执行需要这两个上下文的最终计算。
这是我的新尝试。
上述解决方案的主要问题是没有一个 Promise 是可重用的,并且它们不是链式,这是 Promises 的一个关键特性。
但是,我仍然建议您自己使用 promisifying 您的 request 库,并避免向您的项目添加其他依赖项。 promisifying 自己的另一个好处是您可以编写自己的 rejection 逻辑。如果您正在使用在正文中发送 error 消息的特定 API,这一点很重要。一起来看看吧:
//Function that returns a new Promise. Beats out constructor anti-pattern.
const asyncReq = function(options) {
return new Promise(function (resolve, reject) {
request(options, function(err, response, body) {
//Rejected promises can be dealt with in a `catch` block.
if(err) {
return reject(err);
}
//custom error handling logic for your application.
else if (hasError(body)) {
return reject(toError(body));
}
// typically I just `resolve` `res` since it contains `body`.
return resolve(res);
}
});
};
asyncReq(urlA)
.then(function(resA) {
//Promise.all is the preferred method for managing nested context.
return Promise.all([resA, asyncReq(urlB)]);
})
.then(function(resAB) {
return render('page', resAB[0], resAB[1]);
})
.catch(function(e) {
console.err(e);
});