提交 5d4bc3a4 编写于 作者: Huan (李卓桓)'s avatar Huan (李卓桓)

fix unhandled promise exception for race conditions (#925)

上级 91ee6440
...@@ -113,7 +113,9 @@ bot.start() ...@@ -113,7 +113,9 @@ bot.start()
bot.on('error', async e => { bot.on('error', async e => {
log.error('Bot', 'error: %s', e) log.error('Bot', 'error: %s', e)
await bot.say('Wechaty error: ' + e.message).catch(console.error) if (bot.logonoff()) {
await bot.say('Wechaty error: ' + e.message).catch(console.error)
}
await bot.stop() await bot.stop()
}) })
......
...@@ -160,6 +160,7 @@ export class Bridge extends EventEmitter { ...@@ -160,6 +160,7 @@ export class Bridge extends EventEmitter {
} catch (e) { } catch (e) {
log.error('PuppetWebBridge', 'init() initPage() onLoad() exception: %s', e) log.error('PuppetWebBridge', 'init() initPage() onLoad() exception: %s', e)
await page.close()
this.emit('error', e) this.emit('error', e)
} }
} }
...@@ -200,18 +201,23 @@ export class Bridge extends EventEmitter { ...@@ -200,18 +201,23 @@ export class Bridge extends EventEmitter {
const timer = setTimeout(async () => { const timer = setTimeout(async () => {
log.verbose('PuppetWebBridge', 'readyAngular() timeout') log.verbose('PuppetWebBridge', 'readyAngular() timeout')
const text = await this.evaluate(() => { try {
return document.body.innerHTML const text = await this.evaluate(() => {
}) as any as string // BUG of Puppet Type Definition return document.body.innerHTML
}) as any as string // BUG of Puppet Type Definition
const blockedMessage = await this.testBlockedMessage(text) const blockedMessage = await this.testBlockedMessage(text)
if (blockedMessage) { // Wechat Account Blocked if (blockedMessage) { // Wechat Account Blocked
const err = new Error(blockedMessage) const err = new Error(blockedMessage)
return reject(err) return reject(err)
}
} catch (e) {
log.verbose('PuppetWebBridge', 'readyAngular() timeout exception: %s', e)
return reject(e)
} }
reject(`readyAngular() timeout after ${TIMEOUT}`) return reject(`readyAngular() timeout after ${TIMEOUT}`)
}, TIMEOUT) }, TIMEOUT)
await page.waitForFunction(`typeof window.angular !== 'undefined'`) await page.waitForFunction(`typeof window.angular !== 'undefined'`)
...@@ -283,14 +289,18 @@ export class Bridge extends EventEmitter { ...@@ -283,14 +289,18 @@ export class Bridge extends EventEmitter {
try { try {
await this.page.close() await this.page.close()
log.silly('PuppetWebBridge', 'quit() page.close()-ed') log.silly('PuppetWebBridge', 'quit() page.close()-ed')
} catch (e) {
log.warn('PuppetWebBridge', 'quit() page.close() exception: %s', e)
}
try {
await this.browser.close() await this.browser.close()
log.silly('PuppetWebBridge', 'quit() browser.close()-ed') log.silly('PuppetWebBridge', 'quit() browser.close()-ed')
} catch (e) { } catch (e) {
log.warn('PuppetWebBridge', 'quit() exception: %s', e) log.warn('PuppetWebBridge', 'quit() browser.close() exception: %s', e)
// this.emit('error', e)
} finally {
this.state.off(true)
} }
this.state.off(true)
} }
public async getUserName(): Promise<string> { public async getUserName(): Promise<string> {
...@@ -734,28 +744,35 @@ export class Bridge extends EventEmitter { ...@@ -734,28 +744,35 @@ export class Bridge extends EventEmitter {
// https://github.com/GoogleChrome/puppeteer/issues/537#issuecomment-334918553 // https://github.com/GoogleChrome/puppeteer/issues/537#issuecomment-334918553
async function listXpath(thePage: Page, xpath: string): Promise<ElementHandle[]> { async function listXpath(thePage: Page, xpath: string): Promise<ElementHandle[]> {
const nodeHandleList = await (thePage as any).evaluateHandle(xpathInner => { log.verbose('PuppetWebBridge', 'clickSwitchAccount() listXpath()')
const nodeList: Node[] = []
const query = document.evaluate(xpathInner, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null) try {
for (let i = 0, length = query.snapshotLength; i < length; ++i) { const nodeHandleList = await (thePage as any).evaluateHandle(xpathInner => {
nodeList.push(query.snapshotItem(i)) const nodeList: Node[] = []
const query = document.evaluate(xpathInner, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
for (let i = 0, length = query.snapshotLength; i < length; ++i) {
nodeList.push(query.snapshotItem(i))
}
return nodeList
}, xpath)
const properties = await nodeHandleList.getProperties()
const elementHandleList: ElementHandle[] = []
const releasePromises: Promise<void>[] = []
for (const property of properties.values()) {
const element = property.asElement()
if (element)
elementHandleList.push(element)
else
releasePromises.push(property.dispose())
} }
return nodeList await Promise.all(releasePromises)
}, xpath) return elementHandleList
const properties = await nodeHandleList.getProperties() } catch (e) {
log.verbose('PuppetWebBridge', 'clickSwitchAccount() listXpath() exception: %s', e)
const elementHandleList: ElementHandle[] = [] return []
const releasePromises: Promise<void>[] = []
for (const property of properties.values()) {
const element = property.asElement()
if (element)
elementHandleList.push(element)
else
releasePromises.push(property.dispose())
} }
await Promise.all(releasePromises)
return elementHandleList
} }
const XPATH_SELECTOR = `//div[contains(@class,'association') and contains(@class,'show')]/a[@ng-click='qrcodeLogin()']` const XPATH_SELECTOR = `//div[contains(@class,'association') and contains(@class,'show')]/a[@ng-click='qrcodeLogin()']`
...@@ -779,9 +796,15 @@ export class Bridge extends EventEmitter { ...@@ -779,9 +796,15 @@ export class Bridge extends EventEmitter {
public async hostname(): Promise<string | null> { public async hostname(): Promise<string | null> {
log.verbose('PuppetWebBridge', 'hostname()') log.verbose('PuppetWebBridge', 'hostname()')
const hostname = await this.page.evaluate(() => location.hostname) as any as string try {
log.silly('PuppetWebBridge', 'hostname() got %s', hostname) const hostname = await this.page.evaluate(() => location.hostname) as any as string
return hostname log.silly('PuppetWebBridge', 'hostname() got %s', hostname)
return hostname
} catch (e) {
log.error('PuppetWebBridge', 'hostname() exception: %s', e)
this.emit('error', e)
return null
}
} }
public async cookies(cookieList: Cookie[]): Promise<void> public async cookies(cookieList: Cookie[]): Promise<void>
...@@ -850,9 +873,15 @@ export class Bridge extends EventEmitter { ...@@ -850,9 +873,15 @@ export class Bridge extends EventEmitter {
return return
} }
public async evaluate(fn: () => any, ...args: any[]): Promise<() => any> { public async evaluate(fn: () => any, ...args: any[]): Promise<any> {
log.silly('PuppetWebBridge', 'evaluate()') log.silly('PuppetWebBridge', 'evaluate()')
return await this.page.evaluate(fn, ...args) try {
return await this.page.evaluate(fn, ...args)
} catch (e) {
log.error('PuppetWebBridge', 'evaluate() exception: %s', e)
this.emit('error', e)
return null
}
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册