Env:
我正在创建一个快速应用程序,以将blob上载/从azure blob存储下载。 一切正常:可以上传Blob,设置元数据,下载Blob等。 但是:当中止程序超时时,它们会引起意外的异常,从而终止节点进程。
错误堆栈为:
Fri Apr 19 2019 07:38:28 GMT+0000 (Greenwich Mean Time): Application has thrown an uncaught exception and is terminated:
Error: The request was aborted
at new RestError (D:\home\site\wwwroot\node_modules\@azure\ms-rest-js\dist\msRest.node.js:1397:28)
at a.<anonymous> (D:\home\site\wwwroot\node_modules\mql\node_modules\@azure\storage-blob\dist\index.js:1:11269)
at D:\home\site\wwwroot\node_modules\mql\node_modules\@azure\storage-blob\dist\index.js:1:1277
at Array.forEach (<anonymous>)
at a.abort (D:\home\site\wwwroot\node_modules\mql\node_modules\@azure\storage-blob\dist\index.js:1:1255)
at Timeout.<anonymous> (D:\home\site\wwwroot\node_modules\mql\node_modules\@azure\storage-blob\dist\index.js:1:519)
at ontimeout (timers.js:436:11)
at tryOnTimeout (timers.js:300:5)
at unrefdHandle (timers.js:520:7)
at Timer.processTimers (timers.js:222:12)
在我的本地dev-env中,我对未捕获的异常设置了一个断点,并发现:
事件最终被引发到event.js中(发出)
它是由RetriableReadableStream(@ azure / storage-blob / dist / esm / lib / utils / RetriableReadableStream)引起的,请参阅“ aborter.addEventListener”:
function RetriableReadableStream(aborter, source, getter, offset, count, options) {
if (options === void 0) { options = {}; }
var _this = _super.call(this) || this;
_this.retries = 0;
_this.aborter = aborter;
_this.getter = getter;
_this.source = source;
_this.start = offset;
_this.offset = offset;
_this.end = offset + count - 1;
_this.maxRetryRequests =
options.maxRetryRequests && options.maxRetryRequests >= 0
? options.maxRetryRequests
: 0;
_this.progress = options.progress;
_this.options = options;
aborter.addEventListener("abort", function () {
_this.source.pause();
_this.emit("error", new RestError("The request was aborted", RestError.REQUEST_ABORTED_ERROR));
});
...
Aborter.prototype.abort = function () {
var _this = this;
if (this.aborted) {
return;
}
this.cancelTimer();
if (this.onabort) {
this.onabort.call(this);
}
this.abortEventListeners.forEach(function (listener) {
listener.call(_this);
});
this.children.forEach(function (child) { return child.cancelByParent(); });
this._aborted = true;
};
我的堕胎者是这样创建的:
createAborter(): Aborter {
let aborter = Aborter.timeout(5 * ONE_MINUTE);
aborter.onabort = () => {
console.warn(`AzureBlog.createAborter.onAbort: Request was aborted.`);
}
return aborter;
}
...,我的下载内容如下:
async download(blobName: string): Promise<NodeJS.ReadableStream> {
const blockBlobURL = this.getBlockBlobUrl(blobName);
const downloadResponse = await blockBlobURL.download(this.createAborter(), 0);
if (!downloadResponse) {
throw new Error(`Download returned undefined.`);
}
if (!downloadResponse.readableStreamBody) {
throw new Error(`downloadResponse.readableStreamBody is undefined.`);
}
return downloadResponse.readableStreamBody;
}
...,我像这样将其流式传输到客户端:
self.expressApp.route('/download')
.get(jsonParser, async (req: Request, resp: Response) => {
handleDownload(req, resp);
}).post(jsonParser, async (req: Request, resp: Response) => {
handleDownload(req, resp);
});
...
let blobReadStream = await self.azureBlobStore.download(id);
blobReadStream.pipe(resp);
如上所述,一切正常,直到超时为止。我不明白的是:
我认为我误解了Aborter概念。因此,非常感谢您的帮助。
非常感谢!