【问题标题】:What is wrong with this promisify?这个承诺有什么问题?
【发布时间】:2019-09-01 23:51:32
【问题描述】:

作为练习,我尝试将 https://developers.google.com/sheets/api/quickstart/nodejs 从回调样式转换为承诺样式,然后使用 util.promisify 将其重构为 async/await。

一切都很顺利,直到最后的功能。原文是:

function listMajors(auth) {
  const sheets = google.sheets({version: 'v4', auth});
  sheets.spreadsheets.values.get({
    spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
    range: 'Class Data!A2:E',
  }, (err, res) => {
    if (err) return console.log('The API returned an error: ' + err);
    const rows = res.data.values;
    if (rows.length) {
      console.log('Name, Major:');
      // Print columns A and E, which correspond to indices 0 and 4.
      rows.map((row) => {
        console.log(`${row[0]}, ${row[4]}`);
      });
    } else {
      console.log('No data found.');
    }
  });
}

承诺的版本是:

function listMajors(auth) {
  const sheets = google.sheets({version: 'v4', auth});

  const getValues = util.promisify(sheets.spreadsheets.values.get);
  getValues({
      spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
      range: 'Class Data!A2:E',
    }).then(function (res) {
      const rows = res.data.values;
      if (rows.length) {
        // Print columns A and E, which correspond to indices 0 and 4.
        rows.map((row) => {
          console.log(`${row[0]}, ${row[1]}`);
        });
      }
    }).catch(err => console.log('The API returned an error: ' + err));
}

原始返回电子表格。承诺的版本说,The API returned an error: TypeError: Cannot read property 'context' of undefined。我不明白为什么它们不同。

【问题讨论】:

    标签: node.js google-sheets google-sheets-api


    【解决方案1】:

    您的承诺版本可能会丢失您尝试调用的方法的父对象。

    如果你把它改成这个,这个问题应该得到解决:

    let values = sheets.spreadsheets.values;
    values.getP = util.promisify(sheets.spreadsheets.values.get);
    values.getP().then(...);
    

    这里重要的是,当调用您的承诺版本时,您仍然使用 values 对象引用,就像在 values.getP() 中一样,因此承诺函数仍然获得正确的 this 值。


    仅供参考,您可能还可以将正确的对象绑定到方法:

    const getValues = util.promisify(sheets.spreadsheets.values.get).bind(sheets.spreadsheets.values);
    

    这里有一个简单的例子来演示:

    class Test {
        constructor() {
            this.data = "Hello";
        }
    
        demo() {
            console.log(this);
        }
    }
     
     
    let t = new Test();
    
    // this works just fine
    t.demo();
    
    // this doesn't work because x has lost the t object
    // so when you call x(), it no longer has a reference to the object instance
    // It needs to be called like obj.method()
    let x = t.demo;
    x();

    这种情况经常出现,如果手边有这段 sn-p 代码就好了:

    const util = require('util');
    if (!util.promisifyMethod) {
        util.promisifyMethod = function(fn, obj) {
             return util.promisify(fn).bind(obj);
        }
    }
    

    那么,任何时候你想promisify某个对象的方法,你都可以使用它:

    const getValues = util.promisifyMethod(sheets.spreadsheets.values.get, sheets.spreadsheets.values);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-08
      • 1970-01-01
      • 2019-06-20
      • 1970-01-01
      • 1970-01-01
      • 2016-10-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多