正确地使用Promise和Await / Async

我在理解Promisefunction如何工作时遇到了一些问题,我以前使用过Bluebird,但是我想尝试学习新的await / async标准以提高程序员的性能。 我已经使用了asynchronous/等待,并在适当的地方创build了承诺,但是这些function仍然不按顺序执行。

我正在使用Webpack的最新版本的Node上运行这个,我没有得到任何有意义的错误。 它运行得很好,不像预期的那样。 运行它时我的输出是:

Searching the Web for: Test String Web search Completed! Promise { <pending> } Response Handler Completed! 

理想情况下,我希望它回应:

 Searching the Web for: Test String Response Handler Completed Web search Completed 

然后返回我的响应处理程序的输出。

有谁能发现我的错误?

 const https = require('https'); // Replace the subscriptionKey string value with your valid subscription key. const subscriptionKey = '<samplekey>'; const host = 'api.cognitive.microsoft.com'; const path = '/bing/v7.0/search'; const response_handler = async (response) => { return new Promise((resolve, reject) => { let body = ''; response.on('data', (d) => { body += d; resolve(body); }); response.on('end', () => { console.log('\nRelevant Headers:\n'); for (const header in response.headers) // header keys are lower-cased by Node.js { if (header.startsWith('bingapis-') || header.startsWith('x-msedge-')) { console.log(`${header}: ${response.headers[header]}`); } } body = JSON.stringify(JSON.parse(body), null, ' '); //console.log('\nJSON Test Response:\n'); //console.log(body); }); response.on('error', (e) => { console.log(`Error: ${e.message}`); }); console.log('Response Handler Completed!'); }); }; const bing_web_search = async (search) => { return new Promise((resolve, reject) => { console.log(`Searching the Web for: ${search}`); const request_params = { method: 'GET', hostname: host, path: `${path}?q=${encodeURIComponent(search)}&$responseFilter=${encodeURIComponent('Webpages')}&count=${50}`, headers: { 'Ocp-Apim-Subscription-Key': subscriptionKey, }, }; const req = https.request(request_params, response_handler); console.log('Web search Completed!'); console.log(req.body); req.end(); }); }; module.exports = { search: async (search) => { if (subscriptionKey.length === 32) { const result = await bing_web_search(search); console.log('Search Completed'); } else { console.log('Invalid Bing Search API subscription key!'); console.log('Please paste yours into the source code.'); } }, }; 

有点晚,但下面应该设置你的方式,我对代码进行了更改。 如果您有任何问题,请告诉我。

 const https = require('https'); // Replace the subscriptionKey string value with your valid subscription key. const subscriptionKey = '<samplekey>'; const host = 'api.cognitive.microsoft.com'; const path = '/bing/v7.0/search'; const response_handler = (resolve,reject) => (response) => { // no need for async, you return a promise //this one does not return anything, it's the handler for the response and will resolve // or reject accordingly let body = ''; response.on('data', (d) => { body += d; //cannot resolve yet, we're not done // you can resolve on end maybe? I don't know nodejs http // if end event is called when request fails then end would not // be the correct way either, better use fetch api //resolve(body); }); response.on('end', () => { console.log('\nRelevant Headers:\n'); for (const header in response.headers) // header keys are lower-cased by Node.js { if (header.startsWith('bingapis-') || header.startsWith('x-msedge-')) { console.log(`${header}: ${response.headers[header]}`); } } body = JSON.stringify(JSON.parse(body), null, ' '); resolve(body);//resolving the promise returned by bing_web_search //console.log('\nJSON Test Response:\n'); //console.log(body); }); response.on('error', (e) => { console.log(`Error: ${e.message}`); //need to reject with the error reject(e); }); console.log('Response Handler Completed!'); }; //no need to specify async, you are not awaiting anything // you are creating a promise, when using non promise asynchronous // functions that work with callbacks or event emitting objects // you need resolve and reject functions so you have to return // new Promise( // (resolve,reject)=>somecallbackNeedingFunction((err,result)=> // err ? reject(err) : resolve(result) // ) // ) const bing_web_search = (search) => { return new Promise((resolve, reject) => { console.log(`Searching the Web for: ${search}`); const request_params = { method: 'GET', hostname: host, path: `${path}?q=${encodeURIComponent(search)}&$responseFilter=${encodeURIComponent('Webpages')}&count=${50}`, headers: { 'Ocp-Apim-Subscription-Key': subscriptionKey, }, }; const req = https.request( request_params, response_handler(resolve,reject)//passing this resolve and reject ); //no, request not completed, we just started console.log('Web search Completed!'); // console.log(req.body); // nothing to log here req.end(); }); }; module.exports = { search: async (search) => { if (subscriptionKey.length === 32) { //did not change anything bing_web_search returns a promise // so you can just await it const result = await bing_web_search(search); console.log('Search Completed'); //this will resolve with the results return result } else { console.log('Invalid Bing Search API subscription key!'); console.log('Please paste yours into the source code.'); //the caller of this function can handle the rejection return Promise.reject('Invalid Bing Search API subscription key!'); } }, }; 

[更新]

您的评论build议您不要正确调用search或处理它正确返回的承诺。 您无法控制响应需要多长时间,因此在第一个请求最后可能会返回的一组响应中。 这就是为什么你有Promise.all

 const searchObjects = [s1,s2]; const Fail = function(reason){this.reason=reason;}; Promise.all( searchObjects.map( searchObject => obj.search(searchObject) .then( x=>[x,searchObject]//if resolve just pass result ,err =>new Fail([err,searchObject])//if reject add a Fail object with some detail ) ) ) .then( results => { console.log( "resolved results:", results.filter(([r,_])=>(r&&r.constructor)!==Fail) ); console.log( "failed results:", results.filter(([r,_])=>(r&&r.constructor)===Fail) ); } ) 

如果你有很多的search,那么也许你想限制一定的时间周期或活动连接的回应量。 让我知道你是否需要帮助。