ES7 - 如何用 await 替换 Promise?
ES7 - how can I replace Promise with await?
有一件事让我对 Promise 感到厌烦,那就是 resolve
和 reject
很难掌握。 Promise
包装的需要也很难看。除非你经常使用它,否则我会随着时间的推移忘记如何使用它们。此外,带有 Promise
的代码仍然凌乱且难以阅读。因此我根本不喜欢使用它——因为它与回调地狱没有太大区别。所以我想用 ES7 await
,我可以避免使用 Promise 而让我对 JavaScript 更有信心,但似乎并非如此。例如:
const getOne = async () => {
return Weather.findOne(options, function(err, weather) {
//
});
}
const getWeather = async () => {
const exist = await getOne();
if (exist == null) {
return new Promise(function(resolve, reject) {
// Use request library.
request(pullUrl, function (error, response, body) {
if (!error && response.statusCode == 200) {
// Resolve with the data.
resolve(body);
} else {
// Reject with the error.
reject(error);
}
});
});
}
}
const insertWeather = async () => {
try {
const data = await getWeather();
} catch (err) {
res.set('Content-Type', 'application/json');
return res.status(200).send('Error occurs: ' + err);
}
}
insertWeather();
request(pullUrl, function (error, response, body) {}
是来自 request nodejs 包的 AJAX 调用。
我必须用 Promise
包裹 - 但不能在它前面加上 await
。理想情况下,这就是我的想象:
return await request(pullUrl, function (error, response, body) {...}
但如果我这样做,我将在 return 中获得 请求对象 ,而不是 数据 return 来自 request
包 - 在这一行:
const data = await getWeather();
有什么想法或解决方案可以避免在上述情况下使用 Promise
吗?
如文档 here, you will need to wrap request
with interfaces wrappers like request-promise 中所述(或者您可以在文档中找到替代接口)以便 return 来自 request
的 Promise。
您会发现 bluebird 和 node.js 现在带有 promisify 以允许您在需要时将 Node 回调作为承诺使用。或者,您可以考虑一种功能性反应式方法并使用像 RxJS 这样的库,它将处理承诺、节点回调和其他数据类型到流中。
const promisify = require('utils').promisify // alternatively use bluebird
const request = require('request-promise');
const weatherFn = promisify(Weather.findOne);
const weatherOptions = {};
async function getWeatherIfDoesNotExist() {
try {
const records = await weatherFn(weatherOptions);
if (records === null) {
return await request('/pullUrl');
}
} catch(err) {
throw new Error('Could not get weather');
}
}
async function weatherController(req, res) {
try {
const data = await getWeatherIfDoesNotExist();
} catch (err) {
res.set('Content-Type', 'application/json');
return res.status(200).send('Error occurs: ' + err);
}
}
function altWeatherController(req, res) {
return getWeatherIfDoesNotExist()
.then((data) => { // do something })
.catch((err) => {
res.set('Content-Type', 'application/json');
return res.status(200).send('Error occurs: ' + err);
})
}
有一件事让我对 Promise 感到厌烦,那就是 resolve
和 reject
很难掌握。 Promise
包装的需要也很难看。除非你经常使用它,否则我会随着时间的推移忘记如何使用它们。此外,带有 Promise
的代码仍然凌乱且难以阅读。因此我根本不喜欢使用它——因为它与回调地狱没有太大区别。所以我想用 ES7 await
,我可以避免使用 Promise 而让我对 JavaScript 更有信心,但似乎并非如此。例如:
const getOne = async () => {
return Weather.findOne(options, function(err, weather) {
//
});
}
const getWeather = async () => {
const exist = await getOne();
if (exist == null) {
return new Promise(function(resolve, reject) {
// Use request library.
request(pullUrl, function (error, response, body) {
if (!error && response.statusCode == 200) {
// Resolve with the data.
resolve(body);
} else {
// Reject with the error.
reject(error);
}
});
});
}
}
const insertWeather = async () => {
try {
const data = await getWeather();
} catch (err) {
res.set('Content-Type', 'application/json');
return res.status(200).send('Error occurs: ' + err);
}
}
insertWeather();
request(pullUrl, function (error, response, body) {}
是来自 request nodejs 包的 AJAX 调用。
我必须用 Promise
包裹 - 但不能在它前面加上 await
。理想情况下,这就是我的想象:
return await request(pullUrl, function (error, response, body) {...}
但如果我这样做,我将在 return 中获得 请求对象 ,而不是 数据 return 来自 request
包 - 在这一行:
const data = await getWeather();
有什么想法或解决方案可以避免在上述情况下使用 Promise
吗?
如文档 here, you will need to wrap request
with interfaces wrappers like request-promise 中所述(或者您可以在文档中找到替代接口)以便 return 来自 request
的 Promise。
您会发现 bluebird 和 node.js 现在带有 promisify 以允许您在需要时将 Node 回调作为承诺使用。或者,您可以考虑一种功能性反应式方法并使用像 RxJS 这样的库,它将处理承诺、节点回调和其他数据类型到流中。
const promisify = require('utils').promisify // alternatively use bluebird
const request = require('request-promise');
const weatherFn = promisify(Weather.findOne);
const weatherOptions = {};
async function getWeatherIfDoesNotExist() {
try {
const records = await weatherFn(weatherOptions);
if (records === null) {
return await request('/pullUrl');
}
} catch(err) {
throw new Error('Could not get weather');
}
}
async function weatherController(req, res) {
try {
const data = await getWeatherIfDoesNotExist();
} catch (err) {
res.set('Content-Type', 'application/json');
return res.status(200).send('Error occurs: ' + err);
}
}
function altWeatherController(req, res) {
return getWeatherIfDoesNotExist()
.then((data) => { // do something })
.catch((err) => {
res.set('Content-Type', 'application/json');
return res.status(200).send('Error occurs: ' + err);
})
}