我知道这是一个基本问题,但我自己无法弄明白,如何从“for”循环中导出我的变量“X”(实际上是一个JSON对象)。我尝试了各种方法,但在我的情况下,函数返回的不是JSON.object本身,而是“promise.pending”。
我想那个更有经验的人会帮助我。我的代码:
for (let i = 0; i < server.length; i++) {
const fetch = require("node-fetch");
const url = ''+(server[i].name)+'';
const getData = async url => {
try {
const response = await fetch(url);
return await response.json();
} catch (error) {
console.log(error);
}
};
getData(url).then(function(result) { //promise.pending w/o .then
let x = result; //here is real JSON that I want to export
});
}
console.log(x); // -element is not exported :(
答案 0 :(得分:3)
您可以尝试使用一些更干净的ES6代码:
const fetch = require("node-fetch");
Promise.all(
server.map((srv) => {
const url = String(srv.name);
return fetch(url)
.then((response) => response.json())
.catch((err) => console.log(err));
})
)
.then((results) => {
console.log(results);
})
.catch((err) => {
console.log('total failure!');
console.log(err);
});
它是如何运作的?
使用Array.map
,它将服务器列表转换为并行执行的promise列表。每个承诺都做两件事:
如果任一步骤失败,那一个承诺拒绝,这将导致整个系列立即拒绝。
为什么我认为这比接受的答案更好?总之,它更干净。它没有将显式的promises与async / await混合在一起,这可能使异步逻辑变得比必要的更混乱。它不会在每次循环迭代中导入fetch
库。它明确地将服务器URL转换为字符串,而不是依赖于隐式强制。它不会创建不必要的变量,它可以避免不必要的for
循环。
无论你是否接受,我都将其视为对同一问题的另一种看法,我认为这是一种最优雅,最清晰的方式。
为什么这么难?为什么异步工作如此违反直觉?
做异步工作需要对称为&#34;继续传递风格的事情感到满意。&#34;根据定义,异步任务是非阻塞的 - 在移动到下一个语句之前,程序执行不会等待任务完成。但我们经常进行异步工作,因为后续语句需要尚未提供的数据。因此,我们有回调函数,然后是Promise,现在是async / await。前两个解决问题的机制允许您提供&#34;包&#34;异步任务完成后要做的工作 - &#34; continuation,&#34;一旦条件获得,执行将恢复的地方。枯燥的节点式回调函数和Promise的.then
之间完全没有区别:两者都接受函数,并且两者都将在特定时间和特定数据执行这些函数。回调函数的关键任务是充当异步任务数据的容器。
这种模式不仅使基本变量范围变得复杂,这是您主要关注的问题,也是如何最好地表达复杂工作流的问题,这些工作流通常是阻塞和非阻塞语句的混合。如果做异步工作需要提供大量的继续&#34;以功能的形式,我们知道做这项工作将是一场持续的战斗,反对一百万个小功能的扩散,一百万个需要名称必须独特和清晰的东西。这是一个无法用库解决的问题。它需要根据变化的地形调整一种风格。
你的双脚触地越少越好。 :)
答案 1 :(得分:2)
Javascript建立在承诺的概念之上。当你要求getData
完成它的工作时,说的是,“好的,这需要一些时间,但我保证在工作完成后我会通知你。所以请相信我的承诺,一旦工作完成,我会告诉你“,它会立即给你一个承诺。
这就是你所看到的promise.pending
。它尚未完成,因为尚未完成。现在,您应该使用getData
的承诺注册某个任务(或函数),以便在完成工作时调用。
function doSomething(){
var promiseArray = [];
for (let i = 0; i < server.length; i++) {
const fetch = require("node-fetch");
const url = ''+(server[i].name)+'';
const getData = async url => {
try {
const response = await fetch(url);
return await response.json();
} catch (error) {
console.log(error);
}
};
promiseArray.push(getData(url)); // keeping track of all promises
}
return Promise.all(promiseArray); //see, I'm not registering anything to promise, I'm passing it to the consumer
}
function successCallback(result) {
console.log("It succeeded with " + result);
}
function failureCallback(error) {
console.log("It failed with " + error);
}
let promise = doSomething(); // do something is the function that does all the logic in that for loop and getData
promise.then(successCallback, failureCallback);