API 距离矩阵仅在 Javascript 中调用
Posted
技术标签:
【中文标题】API 距离矩阵仅在 Javascript 中调用【英文标题】:API distance matrix Call in Javascript alone 【发布时间】:2019-11-15 09:19:54 【问题描述】:所以我是一个非常初学者的程序员,试图了解如何使用纯 javascript 从 Google 距离矩阵 API 调用/获取数据。
下面是我的代码
https = require('https')
function getDistance(app)
console.log('testing1');
let defaultPath = 'maps.googleapis.com/maps/api/distancematrix/json?units=metric';
let APIKey = '&key=<API KEY HERE>';
let origin = 'Tampines Avenue 1, Temasek Polytechnic';
let destination = 'Tampines Central 5, Tampines Mall';
let newPath = defaultPath+ '&origins=' + origin + '&destinations=' +destination + APIKey;
console.log('https://'+ newPath); //this prints the correct path
https.get('https://'+ newPath, (res) => //i assume the problem begins here?
console.log('testing2')//doesnt print
let body = ''; //no idea what this does. Copied from a school lab sheet
res.on('data', (d) =>
console.log('testing3') //this doesn't print
let response = JSON.parse(body);
let distance = response.rows[0].elements.distance.text //are these correct?
let travelTime = response.rows[0].elements.duration.text
console.log(distance) //doesnt print
console.log(response.rows[0]) //doesnt print
app.add('distance between is ' + distance + '. Time taken is ' + travelTime);
console.log(response);
);
);
我很确定 'https://'+ newPath 是正确的,因为它打印在 console.log 中
然后将链接扔到浏览器中 我得到了这个结果
所以有人可以向我解释我做错了什么吗? 哦,还有,不知道这是否有必要,但我在 dialogflow.cloud.google.com 中作为我的任务的聊天机器人这样做
这是我得到的错误
错误:没有为平台定义响应:未定义于 WebhookClient.send_ (/srv/node_modules/dialogflow-fulfillment/src/dialogflow-fulfillment.js:428:13) 承诺。那么 (/srv/node_modules/dialogflow-fulfillment/src/dialogflow-fulfillment.js:246:38) 在 process._tickDomainCallback (内部/进程/next_tick.js:229:7)
【问题讨论】:
你能告诉我们问题是什么吗? @LajosArpad “问题从这里开始”在代码的 cmets 中说明。 “https.get('https://'+ newPath, (res) =>" 您是在基于浏览器的 JavaScript 中还是在基于服务器的 NodeJS 中执行此操作?你会得到什么错误?你知道如何检查错误吗? “没有任何效果”不是我们可以解决的问题……我们需要有关错误消息的具体细节,或程序某些意外行为的描述。 这是我得到的错误错误:没有为平台定义响应:未定义在 WebhookClient.send_ (/srv/node_modules/dialogflow-fulfillment/src/dialogflow-fulfillment.js:428:13) 处promise.then (/srv/node_modules/dialogflow-fulfillment/src/dialogflow-fulfillment.js:246:38) at at process._tickDomainCallback (internal/process/next_tick.js:229:7) 【参考方案1】:我在 GitHub 上发现了一个类似的问题:https://github.com/dialogflow/dialogflow-fulfillment-nodejs/issues/22
解决办法是
好的,这就是我为使其正常工作所做的工作。
我使用 request-promise-native 而不是 http 来进行 AJAX 调用。
const rp = require('request-promise-native');
我从 rp 返回的承诺的处理程序返回了一个承诺。
return rp(options).then(data => // Extract relevant details from data. // Add it to the agent. agent.add('Here's the data: ', JSON.stringify(data)); return Promise.resolve(agent); );
完整代码是
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const rp = require('request-promise-native');
const WebhookClient = require('dialogflow-fulfillment');
const Card, Suggestion = require('dialogflow-fulfillment');
const Carousel = require('actions-on-google');
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
const imageUrl = 'https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png';
const imageUrl2 = 'https://lh3.googleusercontent.com/Nu3a6F80WfixUqf_ec_vgXy_c0-0r4VLJRXjVFF_X_CIilEu8B9fT35qyTEj_PEsKw';
const linkUrl = 'https://assistant.google.com/';
const API_KEY = 'YOUR-API-KEY-HERE';
const server = express();
server.use(
bodyParser.urlencoded(
extended: true
)
);
server.use(bodyParser.json());
server.post('/dialog-flow-fulfillment', (request, response) =>
const agent = new WebhookClient( request, response );
function googleAssistantOther(agent)
let conv = agent.conv();
conv.ask(`Sure! Details about $agent.parameters.movie coming your way!`);
return getMovieDataFromOMDb(agent.parameters.movie).then(movie =>
conv.ask(`Okay! So there you go.`);
conv.ask(new Card(
title: `$movie.Title($movie.Year)`,
imageUrl: movie.Poster,
text: `$movie.Rated | $movie.Runtime | $movie.Genre | $movie.Released ($movie.Country)`,
buttonText: 'Website',
buttonUrl: movie.Website || `https://www.imdb.com/title/$movie.imdbID`
));
conv.ask(new Suggestion(`More details`));
conv.ask(new Suggestion(`Another movie`));
agent.add(conv);
return Promise.resolve(agent);
);
function welcome(agent)
agent.add(`Welcome to my agent!`);
function fallback(agent)
agent.add(`I didn't understand`);
agent.add(`I'm sorry, can you try again?`);
function getMovieDetailsOther(agent)
return getMovieDataFromOMDb(agent.parameters.movie).then(movie =>
// const responseDataToSend = `$movie.Title is a $
// movie.Actors
// starer $movie.Genre movie, released in $
// movie.Year
// . It was directed by $movie.Director`;
// console.log(`Generated response as $responseDataToSend`);
// agent.add(responseDataToSend);
agent.add(`Okay! So there you go.`);
agent.add(new Card(
title: `$movie.Title($movie.Year)`,
imageUrl: movie.Poster,
text: `$movie.Rated | $movie.Runtime | $movie.Genre | $movie.Released ($movie.Country)`,
buttonText: 'Website',
buttonUrl: movie.Website || `https://www.imdb.com/title/$movie.imdbID`
));
agent.add(new Suggestion(`More details`));
agent.add(new Suggestion(`Another movie`));
return Promise.resolve(agent);
, error =>
console.log(`Got an error as $error`);
agent.add(`Sorry bout that! An error prevented getting data for: $agent.parameters.movie || 'the requested movie'`
);
)
.catch(function (err)
console.log(`Caught an err as $err`);
agent.add(err);
);
// agent.add(`This message is from Dialogflow's Cloud Functions for Firebase editor!`);
// const newCard = new Card(
// title: `Title: this is a card title`,
// imageUrl: imageUrl,
// text: `This is the body text of a card. You can even use line\n breaks and emoji! ?`,
// buttonText: 'This is a button',
// buttonUrl: linkUrl
// );
// // newCard.setPlatform('facebook');
// agent.add(newCard);
// agent.add(new Suggestion(`Quick Reply`));
// agent.add(new Suggestion(`Suggestion`));
// agent.setContext( name: 'weather', lifespan: 2, parameters: city: 'Rome' );
function moreDetailsOther(agent)
return getMovieDataFromOMDb(agent.parameters.movie).then(movie =>
agent.add(`Okay! I've got you covered on this too.`);
agent.add(`So the $movie.Actors starer $movie.Type is produced by $movie.Production, is directed by $movie.Director`);
agent.add(`It $movie.Awards. It's available in $movie.Language`);
agent.add(`Written by $movie.Writer, it plots $movie.Plot`);
agent.add(new Suggestion(`Stats on the movie`));
agent.add(new Suggestion(`Another movie`));
return Promise.resolve(agent);
, error =>
console.log(`Got an error as $error`);
agent.add(`Sorry bout that! An error prevented getting data for: $agent.parameters.movie || 'the requested movie'`
);
)
.catch(function (err)
console.log(`Caught an err as $err`);
agent.add(err);
);
function movieStatsOther(agent)
return getMovieDataFromOMDb(agent.parameters.movie).then(movie =>
let ratingDetails = `$movie.Title scored `;
movie.Ratings.forEach(rating =>
ratingDetails += `$rating.Value on $rating.Source `
);
agent.add(`Sure! Here are the stats.`);
agent.add(ratingDetails);
agent.add(new Suggestion(`Another movie`));
return Promise.resolve(agent);
, error =>
console.log(`Got an error as $error`);
agent.add(`Sorry bout that! An error prevented getting data for: $agent.parameters.movie || 'the requested movie'`
);
)
.catch(function (err)
console.log(`Caught an err as $err`);
agent.add(err);
);
function getMovieDataFromOMDb(movieName)
const movieToSearch = movieName || 'The Godfather';
const options =
uri: 'https://www.omdbapi.com/',
json: true,
qs:
t: movieToSearch,
apikey: API_KEY
;
return rp(options);
// Run the proper handler based on the matched Dialogflow intent
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Default Fallback Intent', fallback);
if (agent.requestSource === agent.ACTIONS_ON_GOOGLE)
intentMap.set(null, googleAssistantOther);
// intentMap.set('More Details', googleAssistantMoreDetails);
// intentMap.set('Movie Stats', googleAssistantMovieStats);
else
intentMap.set('Get Movie Details', getMovieDetailsOther);
intentMap.set('More Details', moreDetailsOther);
intentMap.set('Movie Stats', movieStatsOther);
agent.handleRequest(intentMap);
);
server.listen(process.env.PORT || 8000, () =>
console.log('Server is up and running...');
);
Codepen:https://codepen.io/siddajmera/pen/eraNLW?editors=0010
【讨论】:
当我使用这个“const rp = require('request-promise-native');”时出现错误错误说“他的云函数部署失败:加载用户代码时函数失败。错误消息:文件 index.js 中的代码无法加载。您是否在 package.json 依赖项中列出了所有必需的模块?详细的堆栈跟踪:错误:找不到模块“request-promise-native”” @CobenYap 请看一下我现在给你的链接中描述的步骤。那里描述了安装步骤:github.com/request/request-promise-native【参考方案2】:您没有显示所有代码,但看起来 getDistance()
是您在未显示的代码中注册的 Intent Handler 函数。
如果是这样,并且您正在对 API 进行异步调用,则需要返回一个 Promise 以表明您正在等待 HTTP 调用完成,然后再发送结果。
如果没有 Promise,函数会在使用 http.get()
进行调用后立即完成,但不会为使用 app.add()
的响应设置任何内容。
虽然可以将基于事件的调用(您现在正在做的事情)转换为 Promise,但如果您不熟悉它并不容易,并且有更好的解决方案。
使用像request-promise 这样的包(更可能是 request-promise-native - 它使用相同的语法,但 request-promise 有文档)要容易得多。这样,您将返回由 http 调用生成的 Promise,并在它的 then()
子句中调用 app.add()
。
我还没有测试过,但它可能看起来像这样:
const rp = require('request-promise-native');
function getDistance(app)
console.log('testing1');
let defaultPath = 'maps.googleapis.com/maps/api/distancematrix/json?units=metric';
let APIKey = '&key=<API KEY HERE>';
let origin = 'Tampines Avenue 1, Temasek Polytechnic';
let destination = 'Tampines Central 5, Tampines Mall';
let newPath = defaultPath+ '&origins=' + origin + '&destinations=' +destination + APIKey;
let url = 'https://'+newPath;
console.log(url);
rp.get(url)
.then( response =>
console.log(response);
let distance = response.rows[0].elements.distance.text
let travelTime = response.rows[0].elements.duration.text
app.add('distance between is ' + distance + '. Time taken is ' + travelTime);
)
.catch( err =>
console.log( err );
app.add('Something went wrong.');
);
;
【讨论】:
当我使用“const rp = require('request-promise-native');”时出现错误错误说“他部署您的云功能失败:加载用户代码时功能失败。错误消息:无法加载文件 index.js 中的代码。您是否在 package.json 依赖项中列出了所有必需的模块?详细的堆栈跟踪:错误:找不到模块“request-promise-native”” 正如错误提示 - 您需要在package.json
文件中列出包依赖项。以上是关于API 距离矩阵仅在 Javascript 中调用的主要内容,如果未能解决你的问题,请参考以下文章
如何以正确的方式在 IOS SWIFT 3 中解析 Google 距离矩阵 API JSON
将纬度和经度放入距离矩阵,python中的google map API