Javascript 正确使用带有wait/Async的承诺
我在理解Promise功能如何工作时遇到了一些问题,我以前使用过Bluebird,但我想尝试学习新的await/async标准,以便作为一名程序员改进。我使用了async/await,并在我认为合适的地方创建了承诺,但是函数仍然在无序执行 我在最新版本的Node with Webpack上运行此操作,没有收到任何有意义的错误。它运行得很好,只是不像预期的那样。运行时的输出是:Javascript 正确使用带有wait/Async的承诺,javascript,node.js,promise,ecmascript-2017,Javascript,Node.js,Promise,Ecmascript 2017,我在理解Promise功能如何工作时遇到了一些问题,我以前使用过Bluebird,但我想尝试学习新的await/async标准,以便作为一名程序员改进。我使用了async/await,并在我认为合适的地方创建了承诺,但是函数仍然在无序执行 我在最新版本的Node with Webpack上运行此操作,没有收到任何有意义的错误。它运行得很好,只是不像预期的那样。运行时的输出是: Searching the Web for: Test String Web search Completed! Pro
Searching the Web for: Test String
Web search Completed!
Promise { <pending> }
Response Handler 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.');
}
},
};
consthttps=require('https');
//用有效的订阅密钥替换subscriptionKey字符串值。
const subscriptionKey='';
const host='api.cognitive.microsoft.com';
常量路径='/bing/v7.0/search';
常量响应\u处理程序=异步(响应)=>{
返回新承诺((解决、拒绝)=>{
让body='';
响应.on('数据',(d)=>{
body+=d;
决议(机构);
});
响应。在('end',()=>{
console.log('\n相关头:\n');
for(响应中的常量标头。标头)
//标题键由Node.js小写
{
if(header.startsWith('bingapi-')| | header.startsWith('x-msedge-')){console.log(`${header}:${response.headers[header]}})}
}
body=JSON.stringify(JSON.parse(body),null“”);
//console.log('\nJSON测试响应:\n');
//控制台日志(主体);
});
响应时间('error',(e)=>{
log(`Error:${e.message}`);
});
log('Response Handler Completed!');
});
};
const bing\u web\u search=async(search)=>{
返回新承诺((解决、拒绝)=>{
log(`在Web上搜索:${search}`);
常量请求参数={
方法:“GET”,
主机名:主机,
路径:`${path}?q=${encodeURIComponent(search)}&$responseFilter=${encodeURIComponent('Webpages')}&count=${50}`,
标题:{
“Ocp Apim订阅密钥”:subscriptionKey,
},
};
const req=https.request(请求参数、响应处理程序);
log('Web搜索已完成!');
控制台日志(请求主体);
请求结束();
});
};
module.exports={
搜索:异步(搜索)=>{
if(subscriptionKey.length==32){
const result=等待bing\u web\u搜索(搜索);
console.log('Search Completed');
}否则{
log('无效的Bing搜索API订阅密钥!');
log('请将您的粘贴到源代码中');
}
},
};
有点晚了,但下面的内容应该会让您有所收获,我对代码做了更改。如果你有任何问题,请告诉我
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!');
}
},
};
如果你有很多搜索,那么也许你想用某种或某种方式来限制回复的数量。如果需要帮助,请告诉我。从异步函数返回承诺没有任何意义。那么它根本不需要是异步的。而且您永远不会调用
resolve
而且,如果出现错误,您应该拒绝()!也许使用fetch api会更简单,它返回一个承诺,工作起来有点像$。ajax
:我将尝试使用fetch而不是https,关于该模块的文档似乎不多。谢谢大家!承诺是ES2015(ES6)的一部分,async/await
是ES2017的一部分。您好,HMR,这并没有解决回复的顺序问题,但这些评论确实有助于我自己的理解,因此我对此表示感谢!我将尝试从https迁移到fetch,看看这是否简化了操作。如果多个请求的顺序很重要,您可以使用search和usePromise将一系列搜索对象映射到promises。all
(更新了答案并提供了示例)
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!');
}
},
};
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)
);
}
)