【问题标题】:call to a function that includes a promise chain调用包含承诺链的函数
【发布时间】:2017-03-26 20:05:34
【问题描述】:

我有一个调用 JS 函数 (NodeJS) 的代码块。它调用的函数包含一个 Promise 链。下面是调用函数的代码:

'use strict'

const request = require('request')

try {
  const data = search('javascript')
  console.log('query complete')
  console.log(data)
} catch(err) {
  console.log(err)
} finally {
  console.log('all done')
}

function search(query) {
  searchByString(query).then( data => {
    console.log('query complete')
    //console.log(JSON.stringify(data, null, 2))
    return data
  }).catch( err => {
    console.log('ERROR')
    console.log(err)
    throw new Error(err.message)
  })
}

function searchByString(query) {
  return new Promise( (resolve, reject) => {
    const url = `https://www.googleapis.com/books/v1/volumes?maxResults=40&fields=items(id,volumeInfo(title))&q=${query}`
    request.get(url, (err, res, body) => {
      if (err) {
        reject(Error('failed to make API call'))
      }
      const data = JSON.parse(body)
      resolve(data)
    })
  })
}

当我运行代码时,控制台显示query complete,后跟搜索结果。

然后我得到一个错误:TypeError: google.searchByString(...).then(...).error is not a function 这没有意义!为什么会触发此错误?

【问题讨论】:

  • 除非你使用一些 Promise 库,否则你需要.catch() 而不是.error()
  • 绝对是.catch,而且,你所拥有的 try/catch 永远不会工作,因为它在同步函数中,而你的 promise 逻辑是异步的。
  • 感谢您发现拼写错误 Madara。为了清楚起见,我将所有代码合并到一个脚本中。现在我得到query complete 但没有数据。我可以看到数据以错误的顺序返回以使 catch 起作用。
  • 您的搜索是异步的,但您尝试使用它同步。查看stackoverflow.com/questions/14220321/… 以更好地理解异步概念

标签: javascript node.js error-handling ecmascript-6 es6-promise


【解决方案1】:

好吧,您将返回值分配给数据,但您没有返回承诺的结果!

这是一个可行的解决方案,我唯一做的就是 a) 在搜索中返回承诺,b) 从已解决的承诺中获取数据。

您可以在https://runkit.com/arthur/5827b17b8795960014335852 上查看并使用此代码

'use strict'

const request = require('request')

try {
  search('javascript')
    .then(
      data => console.log('and the data', data),
      error => console.error('uh - oh', error)
    );
    console.log('the query isn\'t done yet!');
} catch(err) {
  console.error(err);
} finally {
  console.log('all done, or is it?')
}

function search(query) {
  return searchByString(query).then( data => {
    console.log('query complete')
    //console.log(JSON.stringify(data, null, 2))
    return data
  }).catch( err => {
    console.log('ERROR')
    console.log(err)
    throw new Error(err.message)
  })
}

function searchByString(query) {
  return new Promise( (resolve, reject) => {
    const url = `https://www.googleapis.com/books/v1/volumes?maxResults=40&fields=items(id,volumeInfo(title))&q=${query}`
    request.get(url, (err, res, body) => {
      if (err) {
        reject(Error('failed to make API call'))
      }
      const data = JSON.parse(body)
      resolve(data)
    })
  })
}

下面是我从头开始的方法。我认为我在这里最大的改进是使用节点 url 库。始终为您处理字符串转义总是一件好事。在你的情况下,如果用户要提交一个像“don't”这样的字符串,它会中断:)。

require('request');
// request promise is a popular, well tested lib wrapping request in a promise
const request = require('request-promise');
// i like to use url handling libs, they do good things like escape string input.
const url = require('url');

class Search {
    constructor(query) {
        this.query = query;
    }

    fetch() {
        const endpoint = url.parse('https://www.googleapis.com/books/v1/volumes');

        const options = {
            maxResults: 40,
            fields: 'items(id,volumeInfo(title))',
            q: this.query
        }

        endpoint.query = options;

        const callUrl = url.format(endpoint);
        return request.get(callUrl).then(result => JSON.parse(result));
    }
}

const search = new Search('javascript');
search.fetch()
    .then(result => console.log(result))
    .catch(e => console.error('catch:', e));

这是工作代码:https://runkit.com/arthur/5827d5428b24ed0014dcc537

【讨论】:

    【解决方案2】:

    现在我完成了查询,但没有数据。

    这是因为您在 request.get() 操作完成之前登录了 data。本块:

     try {
      const data = search('javascript')
      console.log('query complete')
      console.log(data)
    } catch(err) {
      console.log(err)
    } finally {
      console.log('all done')
    }
    

    同步执行,因此之后的代码。您必须将其更改为:

    data = search('javascript')
    
    .then(function(data){
        console.log('query complete');
        console.log(data);
        console.log('all done')
    })
    .catch(function(err){
        console.log(err);
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-12
      • 2018-07-06
      • 1970-01-01
      • 2017-03-31
      • 1970-01-01
      • 2018-10-03
      • 1970-01-01
      • 2015-03-25
      相关资源
      最近更新 更多