我的问题是我希望我的代码执行以下操作:
我前两步是正确的,但是我的程序并没有像我预期的那样完成最后两步。
此代码试图举例说明我想要实现的目标。仅使用promise
和jsonfile
它是一个简单的应用程序,它详细地表示了我的代码的体系结构,并且只要您安装了两个库,它就可以实现。
let jsonfile = require("jsonfile");
let Promise = require("promise");
let write = Promise.denodeify(jsonfile.writeFile);
let writeOutput = function(filename, content) {
return write(filename, content, {spaces: 4});
};
//Returns a random number each time it is invoked
//after a random period of time between 1s and 6s
let requestSimulator = function() {
return new Promise((fulfil, reject) => {
let randomNum = Math.random();
let wait = Math.floor((Math.random() * 6000) + 2000);
setTimeout(() => fulfil(randomNum), wait, randomNum);
});
};
//Returns an array of rounded numbers
let roundNumbers = function(someNumbers) {
let numbersArr = [];
let tmpNum;
for (let number of someNumbers) {
tmpNum = Math.floor(number);
console.log("Rounded " + number + " to " + tmpNum);
numbersArr.push(tmpNum);
}
return numbersArr;
};
//Receives an array of rounded numbers, and for each number
//makes a new request.
//It then sums the response with the given number.
let sumNumbersBatch = function(numbersArr) {
let promisesArray = [];
for (let number of numbersArr) {
let promise = new Promise((fulfil, reject) => {
requestSimulator()
.then(result => {
let newNum = number + result;
console.log("Summing " + number + " with " + result + "resultint in " + newNum);
fulfil(newNum);
});
});
promisesArray.push(promise);
}
return new Promise.all(promisesArray);
};
//Starts the process
let getData = function() {
return new Promise((fulfil, reject) => {
requestSimulator()
.then(number => fulfil([number, number * 2, number * 3]));
});
};
console.log("Starting program");
getData()
.then(roundNumbers)
.then(sumNumbersBatch)
.then(newNumbers => writeOutput("testFile.txt", newNumbers))
.then(console.log("Program finished"))
.catch(console.log);
运行之后,您可以看到输出类似于:
Starting program
Program finished
Rounded 0.20890058801647582 to 0
Rounded 0.41780117603295164 to 0
Rounded 0.6267017640494275 to 0
Summing 0 with 0.05537663551196226resultint in 0.05537663551196226
Summing 0 with 0.34853429001859215resultint in 0.34853429001859215
Summing 0 with 0.988336787994851resultint in 0.988336787994851
哪个错!!!!
Program finish
应该出现在最后,而不是第二个!
所以现在我对我的代码有疑问:
write
功能吗?此外,我愿意接受有关代码质量的建议!!!!
非常感谢任何帮助和解释。
答案 0 :(得分:4)
我已经重写了整个答案以匹配修改后的代码。我对“答案”的第一次尝试只不过是对第一个提供的代码看似错误的扩展评论;所以什么都没有丢失。
你的大部分代码都是正确的,这一行实际上是“错误的”:
.then(console.log("Program finished"))
并让您感到困惑,因为它会立即调用console.log("Program finished")
并返回undefined
,然后转换为.then(undefined)
。
应该是
.then(() => console.log("Program finished"))
new
Promise.all()
虽然可以改进一些事情,特别是你使用Deferred反模式。这是在没有必要时手动创建延迟对象,当你已经在那个地方处理承诺时。像这样:
//Starts the process
let getData = function() {
return new Promise((fulfil, reject) => {
requestSimulator()
.then(number => fulfil([number, number * 2, number * 3]));
});
};
更好的是
//Starts the process
let getData = function() {
return requestSimulator().then(number => [number, number * 2, number * 3]);
};
而在requestSimulator
中,您需要创建new Promise()
才能将Promises与setTimeout()
一起使用。这是合适的。
let jsonfile = require("jsonfile");
let Promise = require("promise");
let write = Promise.denodeify(jsonfile.writeFile);
//OK, now this function has a purpose/additional value (formatting)
//and is not just forwarding the arguments
let writeOutput = function(filename, content) {
return write(filename, content, {spaces: 4});
};
//fine, a mock
let requestSimulator = function() {
return new Promise((fulfil, reject) => {
let randomNum = Math.random();
let wait = Math.floor((Math.random() * 6000) + 2000);
//there's no need/reason to pass `randomNum` to setTimeout as a third argument
setTimeout(() => fulfil(randomNum), wait);
});
};
//this can be shortened to, although it doesn't log anymore
let roundNumbers = function(someNumbers) {
return someNumbers.map(Math.floor);
};
//Receives an array of rounded numbers, and for each number
//makes a new request.
//It then sums the response with the given number.
let sumNumbersBatch = function(numbersArr) {
//this again can be achieved simpler by using `Array#map` instead of `for..of`
let promisesArray = numbersArr.map(number => {
return requestSimulator()
.then(result => result + number);
});
//no `new` here! Promise.all() is just a utility-function, no constructor.
return Promise.all(promisesArray);
};
//Starts the process
let getData = function() {
//removed the wrapping Promise.
return requestSimulator()
.then(number => [ number, number * 2, number * 3 ]);
};
console.log("Starting program");
getData()
.then(roundNumbers)
.then(sumNumbersBatch)
.then(newNumbers => writeOutput("testFile.txt", newNumbers))
//this executes `console.log()` immediately and passes the result (`undefined`) to `then()`
//.then(console.log("Program finished"))
//but `then()` needs a function:
.then(() => console.log("Program finished"))
//here you pass a reference to the function `console.log`, that's fine
.catch(console.log);
答案 1 :(得分:0)
Promise.all
?是和否,你使用Promise.all
的方式很奇怪 - 你总是提供一个空数组。 Promise.all
期望作为输入的一组承诺,它等待输入中的所有承诺被解析或者它们中的任何一个失败。
它返回一个已解决的promise(如果所有输入promise都可以)或被拒绝(如果失败)。在原始情况下,Promise.all
始终被解析,因为输入列表为空
在从writeOutput
返回的Promise之后调用的中的方法makeBatchRequests
被解析,它被调用两个参数 - fileName
,即{{1因为它从未在您的代码中定义,而第二个是undefined
- 这是一个result
,其成员的解析结果为Array
,它始终为空。从技术上讲,是的,在所有请求完成后调用函数,但没有数据写入文件(哦,实际上,空字符串promisesArray
是{{1}将被打印到文件:])
是,你做得对。
除此之外,尝试重新编写代码,一步一步,在继续执行每个步骤时对其进行测试,并将预期结果与您获得的结果进行比较。 如上面的答案所述,还有很多东西需要修复,祝你好运! :]
答案 2 :(得分:0)
那么,我认为问题可能在writeOutput(fileName, result)
上,你确定它会返回一个承诺吗?
这是一个建议而非实际答案,但尝试这样做:
scrapy.getStanceMods()
.then(['www.google.com', 'www.reddit.com'])
.then(makeBatchRequest)
.then(result => {
return writeOutput(fileName, result))
.then(console.log("Completed."))
.catch(error=>console.log('will catch inner errors'))
})
.catch(error =>console.error(error));