调用包含promise链的函数

时间:2016-11-12 20:50:09

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

我有一个调用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没有意义!为什么会触发此错误?

2 个答案:

答案 0 :(得分:0)

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

这是一个可行的解决方案,我唯一能做的就是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 lib。始终是一件好事,因此可以为您处理字符串转义。在你的情况下,如果用户要输入像“不要”这样的字符串,它会破坏:)。

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

答案 1 :(得分:0)

  

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

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

 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);
})