已保存 javascript facebook API 响应仍未定义?
Saved javascript facebook API response remains undefined?
我怀疑这是异步问题,
我只是无法理解问题出在哪里。
所以我提出了多个 api 请求,并用响应填充了一个列表。
然后我有一个 D3.js 脚本来绘制数据图表,
虽然它收到未定义,但我在这里用一个简单的日志代替了它。
(当然,控制台 "evaluates" 稍后会实时显示值,但记录节点 [0] 项目确实是未定义的。)
我测试了为后续脚本设置超时但无济于事,
自请求以来我无法提出回调解决方案
本身就是一个回调。
(我知道 forEach
是在这里使用的正确方法,但我也试图通过立即 return 使分配起作用,这也是我还无法实现的事情)
variables=["pageid1","pageid2","pageid3"];
nodes=[];
variables.map(function(variable){
FB.api("/"+variable,"GET",{fields:'name,picture.type(large),engagement'},function(response){
if(!response.error){
nodes.push(response);
}
});
});
console.log(nodes);
I suspect it's an issue with asynchronousity
是的,当然,您的 console.log 可以并且将会在 .api
完成之前触发。试图用 setTimeout
延迟它只是糟糕的编程(这是一个猜谜游戏)。
对 nodes
的任何处理都需要在 .api
回调中进行。如果你触发多个异步调用并需要它们在处理 nodes
之前全部完成,你应该使用类似 d3.queue 的东西。来自文档(加粗我的):
A queue evaluates zero or more deferred asynchronous tasks with configurable concurrency: you control how many tasks run at the same time. When all the tasks complete, or an error occurs, the queue passes the results to your await callback. This library is similar to Async.js’s parallel (when concurrency is infinite), series (when concurrency is 1), and queue, but features a much smaller footprint: as of release 2, d3-queue is about 700 bytes gzipped, compared to 4,300 for Async.
在您的情况下,代码可能如下所示(未经测试):
var q = d3.queue();
variables.forEach(function(d) {
q.defer(FB.api, "/" + variable, , "GET", {fields: 'name,picture.type(large),engagement' });
});
q.await(function(error, response1, response2, response3) {
if (error) throw error;
// build out nodes from responses...
});
您可以将请求包装在承诺中。然后等待所有承诺得到解决,在这种情况下,您的节点变量将充满响应。
你可以这样做:
nodes=[];
function sendRequest( variable ) {
return new Promise ( ( resolve, reject ) => {
FB.api("/"+variable,"GET",{fields:'name,picture.type(large),engagement'},function(response){
if(!response.error)
resolve( response );
});
});
}
Promise.all( variables.map(function( variable ) {
return sendRequest( variable );
})).then( values => {
/* All the responses are solved here */
nodes = values.splice( 0 );
console.log( nodes );
});
async/await 的不同方法和一些修复(let、箭头函数,...):
let variables = ['pageid1', 'pageid2', 'pageid3'];
cosnt sendRequest = (variable) => {
return new Promise ((resolve, reject) => {
FB.api('/' + variable, {fields:'name,picture.type(large),engagement'}, (response) => {
if(!response.error) {
resolve(response);
} else {
reject(response.error);
}
});
});
};
const getData = async () => {
let nodes = [];
for (let i = 0; i < variables.length; i++) {
let response = await sendRequest(variables[i]);
nodes.push(response);
}
console.log(nodes);
};
getData();
我怀疑这是异步问题,
我只是无法理解问题出在哪里。
所以我提出了多个 api 请求,并用响应填充了一个列表。
然后我有一个 D3.js 脚本来绘制数据图表,
虽然它收到未定义,但我在这里用一个简单的日志代替了它。
(当然,控制台 "evaluates" 稍后会实时显示值,但记录节点 [0] 项目确实是未定义的。)
我测试了为后续脚本设置超时但无济于事,
自请求以来我无法提出回调解决方案
本身就是一个回调。
(我知道 forEach
是在这里使用的正确方法,但我也试图通过立即 return 使分配起作用,这也是我还无法实现的事情)
variables=["pageid1","pageid2","pageid3"];
nodes=[];
variables.map(function(variable){
FB.api("/"+variable,"GET",{fields:'name,picture.type(large),engagement'},function(response){
if(!response.error){
nodes.push(response);
}
});
});
console.log(nodes);
I suspect it's an issue with asynchronousity
是的,当然,您的 console.log 可以并且将会在 .api
完成之前触发。试图用 setTimeout
延迟它只是糟糕的编程(这是一个猜谜游戏)。
对 nodes
的任何处理都需要在 .api
回调中进行。如果你触发多个异步调用并需要它们在处理 nodes
之前全部完成,你应该使用类似 d3.queue 的东西。来自文档(加粗我的):
A queue evaluates zero or more deferred asynchronous tasks with configurable concurrency: you control how many tasks run at the same time. When all the tasks complete, or an error occurs, the queue passes the results to your await callback. This library is similar to Async.js’s parallel (when concurrency is infinite), series (when concurrency is 1), and queue, but features a much smaller footprint: as of release 2, d3-queue is about 700 bytes gzipped, compared to 4,300 for Async.
在您的情况下,代码可能如下所示(未经测试):
var q = d3.queue();
variables.forEach(function(d) {
q.defer(FB.api, "/" + variable, , "GET", {fields: 'name,picture.type(large),engagement' });
});
q.await(function(error, response1, response2, response3) {
if (error) throw error;
// build out nodes from responses...
});
您可以将请求包装在承诺中。然后等待所有承诺得到解决,在这种情况下,您的节点变量将充满响应。 你可以这样做:
nodes=[];
function sendRequest( variable ) {
return new Promise ( ( resolve, reject ) => {
FB.api("/"+variable,"GET",{fields:'name,picture.type(large),engagement'},function(response){
if(!response.error)
resolve( response );
});
});
}
Promise.all( variables.map(function( variable ) {
return sendRequest( variable );
})).then( values => {
/* All the responses are solved here */
nodes = values.splice( 0 );
console.log( nodes );
});
async/await 的不同方法和一些修复(let、箭头函数,...):
let variables = ['pageid1', 'pageid2', 'pageid3'];
cosnt sendRequest = (variable) => {
return new Promise ((resolve, reject) => {
FB.api('/' + variable, {fields:'name,picture.type(large),engagement'}, (response) => {
if(!response.error) {
resolve(response);
} else {
reject(response.error);
}
});
});
};
const getData = async () => {
let nodes = [];
for (let i = 0; i < variables.length; i++) {
let response = await sendRequest(variables[i]);
nodes.push(response);
}
console.log(nodes);
};
getData();