扩展 JavaScript Promise 时出错
Error when extending JavaScript Promise
我有一个接受回调的Worker
类,但我想通过使其成为Promise
来删除回调,所以我可以做new Worker(stuff, otherStuff).then(function() { ... });
为此,我使用了extends
关键字。
起初,我在this.a = a;
作业中遇到了ReferenceError: this is not defined
错误,但我发现那是因为我不得不打电话给super();
现在,它在this.resolve({output: 'ok'});
行处给出了TypeError: this.resolve is not a function
,所以我试图强行添加this.resolve
和this.reject
函数,但错误不会消失。
这是(高度简化的(代码:
class Worker extends Promise {
constructor(a, b) {
super((resolve, reject) => {
console.log('inside super');
this.resolve = resolve;
this.reject = reject;
});
console.log('start constructing');
this.a = a;
this.b = b;
console.log('A: ' + JSON.stringify(a));
console.log('B: ' + JSON.stringify(b));
this.doStuff();
if (!this.status) {
this.resolve({output: 'ok'});
} else {
this.reject('There was an error');
}
}
doStuff() {}
}
let a = {x: 1};
let b = {z: 2};
console.log('before creation');
let w = new Worker(a, b);
console.log('after creation');
w.then(function() {
console.log('done');
});
我正在使用节点 6.1.0,它似乎支持Promise
子类......我做错了什么?
最佳做法是避免扩展基元类,因为它们会发生变化。扩展它们会使您自己的类受到浏览器/引擎的怜悯。
当你尝试扩展 Promise 类时,this
不会在构造函数中定义,因为现在大多数引擎都不支持子类化 Promise。
此外,工人不是承诺。工人应该工作并做出承诺。
解决方案是使用包装器或工厂模式,而不是继承。
例如,您可以在 Worker
类中定义一个 getter promise
,该 getter 将创建一个新的 Promise
实例并返回它。
function serializeError(error({return{message:error.message||",名称:错误.名称||",堆栈:错误.堆栈||"}}class NativeResolver{constructor(({this.resolve;this.reject;this.promise=new Promise(((resolve,reject(=>{this.resolve=resolve;this.reject=reject}((}}function assertCast(condition({if(!condition({throw new Error("Failed assertion"(}return condition}const ReservedMessageTypes={RESPONSE_TYPE:">response",ERROR_TYPE:">error"};function isGenerated Message(messageType({return messageType.substr(0,3(===">"}function throwIfReserved(messageType({if(isGeneratedMessage(messageType(({throw new Error( Unexpected reserved message type: '${messageType}'
(}}class MessagePipe{constructor(targetOrigin,target,rethrowErrors=true({if(!target({const frame=document.querySelector( iframe[src^='${targetOrigin}']
(;if(!frame||!frame.contentWindow({throw new Error("T无法定位目标内容窗口"(}target=assertCast(frame.contentWindow(}this.target=target;this.targetOrigin=targetOrigin;this.rethrowErrors=rethrowErrors;this.logClientError=object=>console.error(JSON.stringify(object((;this.messageHandlers=new Map;this.pendingMessages_=new Map;this.nextMessageId_=0;this.messageListener_=m=>this.receiveMessage_(m(;console.assert(this.target_!==window,"target !== window"(;window.addEventListener("message",this.messageListener_(}registerHandler(messageType,handler({throwIfReserved(messageType(;if(this.messageHandlers_.has(messageType(({throw new Error( A handler already exists for ${messageType}
(}this.messageHandlers_.set(messageType,handler(}async sendMessage(messageType,message={}({try{return await this.sendMessageImpl(messageType,message(}catch(errorResponse({const error=new Error( ${messageType}: ${errorResponse.message}
(;error.name=errorResponse.name||"Unknown Error";error.stack+= 'nError from ${this.targetOrigin_}'n${errorResponse.stack}
;throw error}}async sendMessageImpl(messageType,message={}({throwIfReserved(messageType(;const messageId=this.nextMessageId_++;const resolver=new NativeResolver;this.pendingMessages_.set(messageId,resolver(;this.postToTarget_(messageType,message,messageId(;return resolver.promise}detach(({window.removeEventListener("message",this.messageListener_(}handleMessageResponse_(messageType,message,messageId({const{RESPONSE_TYPE:RESPONSE_TYPE,ERROR_TYPE:ERROR_TYPE}=ReservedMessageTypes;const resolver=this.pendingMessages_.get(messageId(;if(messageType===RESPONSE_TYPE({resolver.resolve(message(}else if(messageType===ERROR_TYPE({this.logClientError(message(;resolver.reject(message(}else{console.error( Response for message ${messageId} received with invalid message type ${messageType}
(}this.pendingMessages_.delete(messageId(}async callHandlerForMessageType_(messageType,message,messageId({const{RESPONSE_TYPE:RESPONSE_TYPE,ERROR_TYPE:ERROR_TYPE}=ReservedMessageTypes;let response;let error=null;let sawError=false;try{response=await this.messageHandlers_.get(messageType((message(}catch(err({sawError=true;error=err;response=serializeError(err(}this.postToTarget_(sawError?ERROR_TYPE:RESPONSE_TYPE,response,messageId(;if(sawError&&this.rethrowErrors({this.logClientError(error(;throw error}}receiveMessage_(event({const e=event;if(typeof e.data!=="object"||!数据||typeof e.data.type!=="string"({return}const{messageId:messageId,type:type,message:message}=e.data;const{ERROR_TYPE:ERROR_TYPE}=ReservedMessageTypes;if(e.origin!==this.targetOrigin_&&this.targetOrigin_!=="*"({return}if(isGenerated Message(type(&&this.pendingMessages_.has(messageId(({this.handleMessageResponse_(type,message,messageId(;return}if(isGeneratedMessage(type(({console.error( Response with type ${type} for unknown message received.
(;return}if(!this.messageHandlers_.has(type(({const error=new Error( No handler registered for message type '${type}'
(;const errorResponse=serializeError(error(;this.postToTarget_(ERROR_TYPE,errorResponse,messageId(;return}this.callHandlerForMessageType_(type,message,messageId(}postToTarget_(messageType,message,messageId({const messageWrapper={messageId:messageId,type:messageType,message:message||{}};this.target_.postMessage(messageWrapper,this.targetOrigin_(}}
- 使用promise和mongoose对文档进行排序
- javascript中的数组出错
- 节点Js:How to catch a“;没有这样的文件或目录“;读取线模块出错
- 测试Angular Service解决错误回调中的promise
- 在Meteor项目中安装并包含npm模块后出错
- 解析JSON并从中删除对象会出错
- AngularJS指令出错-无法读取属性'编译'的未定义
- 节点协同与生成器和Promise并行流量控制
- 使用javascript在MVC中查找网格长度时出错
- 尝试调用AngularJS上的函数时出错
- 根据是否解析了 Promise 从函数返回值
- Google 脚本:用于创建日历活动的脚本运行时不会出错,但不会执行任何操作
- 全局安装gull后出错
- 我在代码点火器中出错
- 将一个方法转换为promise:Nodejs
- 扩展 JavaScript Promise 时出错
- 在另一个函数中调用promise函数时出错
- 可能未处理在promise中返回promise时出错
- 使用Mocha测试Promise时出错'TypeError: Cannot read property '
- AngularJS模块在放入promise中时出错