【发布时间】:2019-03-07 13:27:08
【问题描述】:
我在这里遇到了一些关于 JS Promises 的基本问题。这是我的完整代码
'use strict'
const rp = require('request-promise');
const cheerio = require('cheerio');
var fs = require('fs');
var os = require('os');
const options = {
uri: url,
normalizeWhitespace: true,
transform: function (body) {
return cheerio.load(body);
}
};
let results = []
let results2 = []
rp(options)
.then(($) => {
$('.col-xs-4 .grid-item').each(function (i, elem) {
let temp = $(this).find(".prod-image").attr("style")
let productImageUrl = temp.substring(temp.indexOf("background-image:url('") + 22, temp.indexOf("')"))
let detailUrl = $(this).find(".prod-image").attr("href")
let title = $(this).find(".title").text()
let description = $(elem).children().eq(4).attr("content")
results.push({
"productImageUrl": productImageUrl,
"detailUrl": detailUrl,
"title": title,
"description": description
})
});
})
.then(() => {
results.forEach(item => {
const options1 = {
uri: item.detailUrl,
normalizeWhitespace: true,
transform: function (body) {
return cheerio.load(body);
}
};
rp(options1)
.then(($) => {
console.log(5)
let temp = $('#prod-title').text()
let unit = temp.substring(temp.indexOf('Size: ') + 6, temp.indexOf('mL') - 1)
let retail = temp.substring(temp.indexOf('Retail: $') + 9, temp.indexOf(' A'))
let wholesale = temp.substring(temp.indexOf('Wholesale: $') + 12, temp.indexOf(' A') + 21)
results2.push({
"productImageUrl": item.productImageUrl,
"detailUrl": item.detailUrl,
"title": item.title,
"description": item.description,
"unit": unit,
"retail": retail,
"wholesale": wholesale
})
})
.catch((err) => {
console.log(err);
});
})
})
.finally(() => {
console.log("FINALLY " + results2)
let header = "Handle,Title,Body" + os.EOL
fs.writeFile("./file.csv", header, function (err) {
if (err) {
return console.log(err);
}
});
for (let item of results2) {
console.log(2)
let hyphenateTitle = item.title.replace(/\s+/g, '-').toLowerCase();
let line = hyphenateTitle + "," + item.title + "," + item.description + "," + vendor + ',"","",true,Title,Default Title,,,,,SKU,10000,,1,deny,manual,' + item.retail + "," + item.wholesale + "," + 'true,true,"",' + item.productImageUrl + "," + ',1,,false,,,,,,,,,,,,,,,,,kg,' + os.EOL
fs.appendFile("./file.csv", line, function (err) {
if (err) {
return console.log(err);
} else {
// done
}
})
}
})
.catch((err) => {
console.log(err);
});
这个想法是,在第一个then() 中,我将阅读 HTML 页面并找到一些 URL。我会将这些信息推送到results 数组。
然后,在第二个then 的想法是遍历数组中的每个项目并转到第二页,提取更多信息并将其推送到results
Finally,在 csv 中获取全部信息。
这是控制台中的输出:
FINALLY
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
所以你可以看到最后一个then 在中间的之前运行(但在最上面的之后。
我做错了什么? 谢谢
编辑 1 这是评论者建议的新代码:
'use strict'
const rp = require('request-promise');
const cheerio = require('cheerio');
var fs = require('fs');
var os = require('os');
const options = {
uri: url,
normalizeWhitespace: true,
transform: function (body) {
return cheerio.load(body);
}
};
let results = []
let results2 = []
rp(options)
.then(($) => {
console.log("FIRST THEN")
$('.col-xs-4 .grid-item').each(function (i, elem) {
let temp = $(this).find(".prod-image").attr("style")
let productImageUrl = temp.substring(temp.indexOf("background-image:url('") + 22, temp.indexOf("')"))
let detailUrl = $(this).find(".prod-image").attr("href")
let title = $(this).find(".title").text()
let description = $(elem).children().eq(4).attr("content")
results.push({
"productImageUrl": productImageUrl,
"detailUrl": detailUrl,
"title": title,
"description": description
})
});
})
.then(($) => {
console.log("SECOND THEN")
return Promise.all(results.map( item => {
console.log("SECOND THEN INNER")
const options1 = {
uri: item.detailUrl,
normalizeWhitespace: true,
transform: function (body) {
return cheerio.load(body);
}
};
rp(options1)
.then(($) => {
console.log("SECOND THEN INSIDE 'rp(options1)'")
let temp = $('#prod-title').text()
let unit = temp.substring(temp.indexOf('Size: ') + 6, temp.indexOf('mL') - 1)
let retail = temp.substring(temp.indexOf('Retail: $') + 9, temp.indexOf(' A'))
let wholesale = temp.substring(temp.indexOf('Wholesale: $') + 12, temp.indexOf(' A') + 21)
results2.push({
"productImageUrl": item.productImageUrl,
"detailUrl": item.detailUrl,
"title": item.title,
"description": item.description,
"unit": unit,
"retail": retail,
"wholesale": wholesale
})
})
.catch((err) => {
console.log(err);
});
}))
})
.finally(($) => {
console.log("FINALLY " + results2)
let header = "Handle,Title,Body" + os.EOL
fs.writeFile("./file.csv", header, function (err) {
if (err) {
return console.log(err);
}
});
for (let item of results2) {
console.log(2)
let hyphenateTitle = item.title.replace(/\s+/g, '-').toLowerCase();
let line = hyphenateTitle + "," + item.title + "," + item.description + "," + vendor + ',"","",true,Title,Default Title,,,,,SKU,10000,,1,deny,manual,' + item.retail + "," + item.wholesale + "," + 'true,true,"",' + item.productImageUrl + "," + ',1,,false,,,,,,,,,,,,,,,,,kg,' + os.EOL
fs.appendFile("./file.csv", line, function (err) {
if (err) {
return console.log(err);
} else {
// done
}
})
}
})
.catch((err) => {
console.log(err);
});
这是输出:
FIRST THEN
SECOND THEN
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
SECOND THEN INNER
FINALLY
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
SECOND THEN INSIDE 'rp(options1)'
【问题讨论】:
-
最后一个 then 在第二个之内,而不是在它之后,因此它将被执行,而(中间)执行给出你得到的结果
标签: javascript node.js asynchronous promise es6-promise