【问题标题】:TypeScript/SPFx Promises throws Exception("Cannot read property 'then' of undefined") but seems to workTypeScript/SPFx Promises throws Exception("Cannot read property 'then' of undefined") 但似乎有效
【发布时间】:2017-07-16 23:13:25
【问题描述】:

我尝试创建一个 SPFx Webpart。在创建新项目之前,我需要调用 0-4 次 _ensureUser,这取决于是否设置了 ClientAssignedToResolvedByReferrer 的任何组合。当所有必需的_ensureUser 调用完成后,就可以创建新项目了。

代码在托管工作台上调试时运行,但在我调用 userPromises[0].then( (value: {}) => { ...Promise.all(userPromises).then( (value: {}[]) => { ... 时抛出异常。当我单击 F5/继续时,将执行其余部分并创建新项目。 _ensureUser 在我直接调用它并将其与 then 链接时起作用,而不是先将其放入 userPromises 数组中。

我认为问题在于,_ensureUser 不会返回 Promise。如果是这样,我该怎么做?我应该重组_ensureUser 和/或createItem 吗?我需要在某处调用 bind 吗?

createItem 函数:

public createItem( logItem: IInteractionLogItem): Promise<IInteractionLogItem[]> {
  const userPromises: Promise<{}>[] = [];

  if(logItem.Client && logItem.Client.AccountName){
    userPromises.push(this._ensureUser(logItem.Client));
  }

  if(logItem.AssignedTo && logItem.AssignedTo.AccountName){
    userPromises.push(this._ensureUser(logItem.AssignedTo));
  }

  if(logItem.ResolvedBy && logItem.ResolvedBy.AccountName){
    userPromises.push(this._ensureUser(logItem.ResolvedBy));
  }

  if(logItem.Referrer && logItem.Referrer.AccountName){
    userPromises.push(this._ensureUser(logItem.Referrer));
  }

  console.log("SharePointDataProvider.CreateItem: userPromises.length=" + userPromises.length);

  if( userPromises.length == 0) {
      const batch: SPHttpClientBatch = this.webPartContext.spHttpClient.beginBatch();

      const batchPromises: Promise<{}>[] = [
        this._createItem(batch, logItem),
        this._getItemsBatched(batch)
      ];

      return this._resolveBatch(batch, batchPromises);
  } else if( userPromises.length == 1) {
    userPromises[0].then( (value: {}) => {
      const batch: SPHttpClientBatch = this.webPartContext.spHttpClient.beginBatch();

      const batchPromises: Promise<{}>[] = [
        this._createItem(batch, logItem),
        this._getItemsBatched(batch)
      ];

      return this._resolveBatch(batch, batchPromises);
    });
  } else {
    Promise.all(userPromises).then( (value: {}[]) => {
      const batch: SPHttpClientBatch = this.webPartContext.spHttpClient.beginBatch();

      const batchPromises: Promise<{}>[] = [
        this._createItem(batch, logItem),
        this._getItemsBatched(batch)
      ];

      return this._resolveBatch(batch, batchPromises);
    });
  }
}

_ensureUser 函数:

private _ensureUser( user: IInteractionLogPerson): Promise<ISPUser> {
  console.log("SharePointDataProvider.EnsureUser( \"" + user.AccountName + "\" )");
  var data = {logonName: user.AccountName};

  return this._webPartContext.spHttpClient.post(
    this._ensureUserUrl, 
    SPHttpClient.configurations.v1,
    { body: JSON.stringify(data) } ).then(
      (value: SPHttpClientResponse) => {
        console.log("SharePointDataProvider.EnsureUser Got Http Response:\"" + value.statusText + "\"" );
        return value.json();
      },
      (error: any) => console.log("SharePointDataProvider.EnsureUser Rejected: " + error )
    ).then((spUser: ISPUser) => {
      console.log("SharePointDataProvider.EnsureUser Set Id:" + spUser.Id +" LoginName:\"" + spUser.LoginName + "\"" );
      user.Id = spUser.Id;
      return spUser;
    });
}

1 个_ensureUser 调用的调试输出:

SharePointDataProvider.EnsureUser( "i:0#.f|membership|bob@pc.org.nz" )
SharePointDataProvider.CreateItem: userPromises.length=1
TypeError: Cannot read property 'then' of undefined
    at ILoggerContainer._createInteractionLogItem (d:\spfx\iLogger-webpart\dist\i-logger.bundle.js:22103:60)
    at ILoggerForm._handleAddButtonClick (d:\spfx\iLogger-webpart\dist\i-logger.bundle.js:23173:21)
    at Object.r (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:75541)
    at a (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:30260)
    at Object.s [as executeDispatchesInOrder] (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:30475)
    at f (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:26933)
    at m (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:27059)
    at Array.forEach (<anonymous>)
    at r (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:112499)
    at Object.processEventQueue (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:28121)
SharePointDataProvider.EnsureUser Got Http Response:"OK"
SharePointDataProvider.EnsureUser Set Id:13 LoginName:"i:0#.f|membership|bob@pc.org.nz"

2 个_ensureUser 调用的调试输出:

SharePointDataProvider.EnsureUser( "i:0#.f|membership|dennis@carehouse.org.nz" )
SharePointDataProvider.EnsureUser( "i:0#.f|membership|bob@pc.org.nz" )
SharePointDataProvider.CreateItem: userPromises.length=2
TypeError: Cannot read property 'then' of undefined
    at ILoggerContainer._createInteractionLogItem (d:\spfx\iLogger-webpart\dist\i-logger.bundle.js:22103:60)
    at ILoggerForm._handleAddButtonClick (d:\spfx\iLogger-webpart\dist\i-logger.bundle.js:23173:21)
    at Object.r (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:75541)
    at a (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:30260)
    at Object.s [as executeDispatchesInOrder] (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:30475)
    at f (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:26933)
    at m (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:27059)
    at Array.forEach (<anonymous>)
    at r (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:112499)
    at Object.processEventQueue (https://spoprod-a.akamaihd.net/files/sp-client-prod_2017-06-30.017/sp-webpart-workbench-assembly_en-us_f3fed222daad2a0117a4c168deed7705.js:174:28121)
SharePointDataProvider.EnsureUser Got Http Response:"OK"
SharePointDataProvider.EnsureUser Set Id:10 LoginName:"i:0#.f|membership|dennis@carehouse.org.nz"
SharePointDataProvider.EnsureUser Got Http Response:"OK"
SharePointDataProvider.EnsureUser Set Id:13 LoginName:"i:0#.f|membership|bob@pc.org.nz"

【问题讨论】:

  • 如果我的结构/模式是错误的/糟糕的,请提供一个示例如何正确构建它。我对整个 Promise 很陌生,之前已经实现了反模式:-)

标签: javascript typescript promise spfx


【解决方案1】:

我需要在调用userPromises[0].then( (value: {}) =&gt; { ...Promise.all(userPromises).then( (value: {}[]) =&gt; { ... 之前添加return。该代码现在可以进行以下修改:

return userPromises[0].then( (value: {}) => {

return Promise.all(userPromises).then( (value: {}[]) => {

【讨论】:

    【解决方案2】:
    return ctx.spHttpClient.get(
            url+'/_api/web/lists',
            SPHttpClient.configurations.v1,
            {
                headers: [
                    ['accept', 'application/json;odata.metadata=none']
                ]
            }
        ).then((response: SPHttpClientResponse):Promise<ILists> => {
            return response.json();
        });
    

    【讨论】:

      猜你喜欢
      • 2020-11-06
      • 1970-01-01
      • 2023-01-19
      • 1970-01-01
      • 2018-07-16
      • 2021-06-25
      • 2020-01-21
      • 2012-07-30
      • 2021-09-25
      相关资源
      最近更新 更多