【发布时间】:2016-08-22 18:53:33
【问题描述】:
我正在从网站提取数据。被拉取的数据是分页的。当向第一页发出请求时,会收到包含nextCursor 的响应。此游标必须用于获取第 2 页的结果。每个页面请求都需要一个nextCursor。
我正在努力使用 Promises 来实现这一点,因为我找不到任何循环方式。这就是我假设它在没有 Promise 的情况下工作的方式(未经测试,但它展示了我正在尝试做的事情):
let nextCursor = argv.initalCursor
do {
let r = request('http://example.com/items.php?cursor=' + nextCursor, function(err, resp, body) {
if(err) throw new Error(err)
// Do something with the data
nextCursor = JSON.parse(body)['nextCursor']
})
} while(nextCursor)
如您所见,循环中的迭代次数是未知的。它将循环直到响应中没有nextCursor。
我想做的是使用 Promises 来实现它。除了我不知道如何创建一个以类似方式工作的循环,因为每个请求都依赖于最后一个。
使用 Promise 会如何工作?
这是我当前的解决方案,当 return self.cursorRequest 时失败。该脚本只是停止执行。
'use strict'
let Promise = require('bluebird')
let _ = require('lodash')
class Event {
constructor(session) {
this.session = session
this.scrapedIDs = [] // I don't like this!
}
parseGuestsAndCursor(json, guestType) {
let ids = json['payload'][guestType]['sections'][2][1].map(function(user) {
return user['uniqueID']
})
return {
ids: _.uniq(ids),
cursor: json['payload'][guestType]['cursor']
}
}
cursorRequest(cursor, eventID, guestType) {
let self = this
return new Promise(function(resolve, reject) {
let url = `https://example.com/events/typeahead/guest_list/?event_id=${eventID}&tabs[0]=${guestType}&order[${guestType}]=affinity&bucket_schema[${guestType}]=friends&cursor[${guestType}]=${cursor}&dpr=1&__user=${self.session.uid}&__a=1`
self.session.request(url, function(err, resp, body) {
if(err) reject(err)
let json
try {
json = JSON.parse(body.substring(9))
} catch(err) {
reject(err)
}
resolve(self.parseGuestsAndCursor(json, guestType))
})
})
}
members(eventID, limit, guestType) {
let self = this
let ids = []
return new Promise(function(resolve, reject) {
let url = `https://example.com/events/typeahead/guest_list/?event_id=${eventID}&tabs[0]=watched&tabs[1]=going&tabs[2]=invited&order[declined]=affinity&order[going]=affinity&order[invited]=affinity&order[maybe]=affinity&order[watched]=affinity&order[ticket_purchased]=affinity&bucket_schema[watched]=friends&bucket_schema[going]=friends&bucket_schema[invited]=friends&bucket_schema[ticket_purchased]=friends&dpr=1&__user=${self.session.uid}&__a=1`
self.session.request(url, function(err, resp, body) {
if(err) reject(new Error(err))
let json, guests
try {
json = JSON.parse(body.substring(9))
guests = self.parseGuestsAndCursor(json, guestType)
} catch(err) {
reject(err)
}
self.cursorRequest(guests.cursor, eventID, guestType).then(function(guests) {
self.scrapedIDs.concat(guests.ids).map(function(user) {
return user['uniqueID']
})
if(guests.cursor) {
return self.cursorRequest(guests.cursor, eventID, guestType)
}
else {
resolve(self.scrapedIDs)
}
})
})
})
}
}
module.exports = Event
【问题讨论】:
-
我根本看不到任何承诺。
-
@T.J.Crowder 没有,因为我不知道如何实现我想要用承诺做的事情。这就是为什么我要问,这种事情如何用承诺来完成?我不需要解决方案,只需要指向任何可以提供帮助的资源的指针。
-
您希望 Promise 等到所有数据都检索完毕后再解析?
-
@Bergi 是的,我确实看到了。但是,因为下一个请求取决于上一个请求的数据,所以我觉得它没有用。而通过使用递归得出的解决方案,我能够将所需的数据传递回函数。
标签: javascript node.js promise