2016-11-12 86 views
-2

我有一段调用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

除非您使用某个Promise库,否则您需要'.catch()'而不是'.error()'。 –

+1

肯定'.catch',而且,您拥有的try/catch将永远不会工作,因为它在同步函数内,并且您的承诺逻辑是异步的。 – loganfsmyth

+0

感谢您发现错字Madara。为了清晰起见,我已将所有代码整合到一个脚本中。现在我得到'query complete',但没有数据。我可以看到数据以错误的顺序返回以使捕获工作。 –

回答

0

好吧,你正在给数据分配返回值,但是你没有返回promise的结果!

这里有一个适合你的工作解决方案,我唯一做的事情就是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

0

Now I get query complete but no data.

那是因为你登录datarequest.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); 
})