【问题标题】:ES7 - how can I replace Promise with await?ES7 - 如何用等待替换 Promise?
【发布时间】:2017-12-08 01:23:38
【问题描述】:

Promise 让我很反感的是,resolvereject 很难掌握。还需要为 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) {...}

但如果我这样做,我将得到 request object 作为回报,而不是从 request 包返回的 data - 在这一行:

const data = await getWeather();

有什么想法或解决方案可以避免在上述情况下使用Promise

【问题讨论】:

  • 仅供参考,有一个名为 request-promise 的流行库可以为您省去麻烦:npmjs.com/package/request-promise
  • 你不能用 await 替换 Promise,因为 async/await 是与 Promise 一起工作的语法糖。您可以承诺请求包或使用一些基于生成器的协程库来处理节点样式回调(但后者会更难掌握)
  • Promise 本身是基于回调的。它们与“回调地狱”的不同之处在于嵌套是相当有限的。所以不,没关系,应该和await一起使用,而不是被它取代。在 Node 8 中已经有 nodejs.org/api/util.html#util_util_promisify_original,并且大多数主要的 Node 库都有承诺的包。

标签: node.js express mongoose promise ecmascript-2017


【解决方案1】:

正如文档here 中提到的,您需要使用request-promise 之类的接口包装器来包装request(或者您可以在文档中找到替代接口),以便从request 返回一个Promise。

【讨论】:

    【解决方案2】:

    您会发现 bluebird 和 node.js 现在带有 Promisify,允许您在需要时将 Node 回调作为 Promise 使用。或者,您可以考虑使用函数式响应式方法并使用 RxJS 之类的库,该库将 Promise、节点回调和其他数据类型处理到流中。

    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 看起来好多了!
    • 我们开始看起来像一种强类型语言! :) 是的 TC39
    • TC39 是关于什么的?
    • 来自 Exploring JS:“TC39(Ecma Technical Committee 39)是发展 JavaScript 的委员会。其成员是公司(除其他外,所有主要浏览器供应商)。TC39 定期开会,其会议由成员派出的代表和受邀专家的代表。会议纪要可在线获取,让您对 TC39 的工作方式有一个很好的了解。”
    猜你喜欢
    • 2017-02-10
    • 2018-07-10
    • 1970-01-01
    • 2018-08-13
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-09
    相关资源
    最近更新 更多