你如何在ReactJS中限制静态方法?

时间:2016-03-13 23:55:16

标签: javascript reactjs underscore.js throttling

我正在尝试编写一个Nylas N1插件,所以我开始只是修改内置的拼写检查(这里是https://github.com/nylas/N1/blob/master/internal_packages/composer-spellcheck/lib/spellcheck-composer-extension.es6)。我导入了下划线库,并试图限制_wrapMisspelledWords函数:

import _ from 'underscore';
...
export default class SpellcheckComposerExtension extends ComposerExtension {
  ...
  static onContentChanged({editor}) {
    SpellcheckComposerExtension.update(editor);
  }

  static update = (editor) => {
    SpellcheckComposerExtension._unwrapWords(editor);
    SpellcheckComposerExtension._wrapMisspelledWords(editor);
  }

  static _wrapMisspelledWords = _.throttle((editor) => {
    console.log('wrap mispelled words');
    ...
    ...
  }, 2000)
  ...
}

它似乎首先正确加油,然后似乎卡在某个循环中,不断重复先前更改的输出。我已经阅读了另一个帖子(Perform debounce in React.js),但无法弄清楚为什么会发生这种情况。

编辑:

限制更新功能可能更有意义,但我看到同样的问题。

编辑:

确定而不是限制或去抖动,我决定将更新函数包装在setTimeout(...,0)中以便进行调试,并且仍然显示同样的问题。

进入无限循环的条件似乎是:

  • 至少有一个拼写错误(因此解包和换行说他们已经修改了内容)
  • 更新功能被添加到事件队列中而不是立即触发(使用setTimeout,throttle或debounce)

contenteditable组件(https://github.com/nylas/N1/blob/1b4739335f4452faa720914309c5e6a593db531d/src/components/contenteditable/contenteditable.cjsx#L302-L333)有一个变异观察者,在扩展运行时停止监听,我认为当我将更新添加到事件队列时,它会在更新运行之前开始侦听突变,导致另一个要观察的突变,进入无限循环。

任何解决方案或提示?

1 个答案:

答案 0 :(得分:1)

我知道这里有点晚了,但是我之前也做过同样的事情。

DEBUG: AzureQoSEvent: CommandName - Connect-AzureRmAccount; IsSuccess - False; Duration - 00:00:19.9521148; Exception - Microsoft.Azure.Commands.Common.Authentica
tion.AadAuthenticationFailedException: accessing_ws_metadata_exchange_failed: Accessing WS metadata exchange failed: The underlying connection was closed: An unex
pected error occurred on a send. ---> Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException: accessing_ws_metadata_exchange_failed: Accessing WS me
tadata exchange failed ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: Una
ble to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existin
g connection was forcibly closed by the remote host
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
   at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.ConnectStream.WriteHeaders(Boolean async)
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.GetResponse()
   at Microsoft.IdentityModel.Clients.ActiveDirectory.HttpWebRequestWrapper.<GetResponseSyncOrAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.MexParser.<FetchMexAsync>d__4.MoveNext()
   --- End of inner exception stack trace ---
   at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.RunAsyncTask[T](Task`1 task)
   at Microsoft.Azure.Commands.Common.Authentication.UserTokenProvider.DoAcquireToken(AdalConfiguration config, PromptBehavior promptBehavior, Action`1 promptActi
on, String userId, SecureString password)
   at Microsoft.Azure.Commands.Common.Authentication.UserTokenProvider.SafeAquireToken(AdalConfiguration config, String showDialog, Action`1 promptAction, String 
userId, SecureString password, Exception& ex)
   --- End of inner exception stack trace ---
   at Microsoft.Azure.Commands.Common.Authentication.UserTokenProvider.AcquireToken(AdalConfiguration config, String promptBehavior, Action`1 promptAction, String
 userId, SecureString password)
   at Microsoft.Azure.Commands.Common.Authentication.UserTokenProvider.GetAccessToken(AdalConfiguration config, String promptBehavior, Action`1 promptAction, Stri
ng userId, SecureString password, String credentialType)
   at Microsoft.Azure.Commands.Common.Authentication.Factories.AuthenticationFactory.Authenticate(IAzureAccount account, IAzureEnvironment environment, String ten
ant, SecureString password, String promptBehavior, Action`1 promptAction, IAzureTokenCache tokenCache, String resourceId)
   at Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient.AcquireAccessToken(IAzureAccount account, IAzureEnvironment environment, String tenantId, Se
cureString password, String promptBehavior, Action`1 promptAction)
   at Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient.ListAccountTenants(IAzureAccount account, IAzureEnvironment environment, SecureString passwo
rd, String promptBehavior, Action`1 promptAction)
   at Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient.Login(IAzureAccount account, IAzureEnvironment environment, String tenantId, String subscrip
tionId, String subscriptionName, SecureString password, Boolean skipValidation, Action`1 promptAction, String name)
   at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.<>c__DisplayClass83_0.<ExecuteCmdlet>b__0(AzureRmProfile localProfile, RMProfileClient profile
Client, String name)
   at Microsoft.Azure.Commands.Profile.Common.AzureContextModificationCmdlet.ModifyContext(Action`2 contextAction)
   at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.SetContextWithOverwritePrompt(Action`3 setContextAction)
   at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.ExecuteCmdlet()
   at Microsoft.WindowsAzure.Commands.Utilities.Common.AzurePSCmdlet.ProcessRecord();
DEBUG: Finish sending metric.
DEBUG: 11:22:02 AM - ConnectAzureRmAccountCommand end processing.
DEBUG: 11:22:02 AM - ConnectAzureRmAccountCommand end processing.

此模式对class Thing { static someFn() { // whatever you do } static heavyAJAX() { // some heavy ajax } } Thing.someFn = _.throttle(Thing.someFn, 2000); Thing.heavyAJAX = _.debounce(Thing.heavyAJAX, 1000); throttle有用。您还可以对实例方法使用相同的方法。如果我们的方法不是debounce,则只需使用static

Thing.prototype

如果要使用实例方法来执行此操作,我建议在构造函数中使用镇静方法:

Thing.prototype.someFn = _.throttle(Thing.prototype.someFn, 2000);
Thing.prototype.heavyAJAX = _.debounce(Thing.prototype.heavyAJAX, 1000);