2017-07-20 21 views
0

我目前正在開發一個插件,利用文本到語音來說出文檔中的每個句子。我使用跟蹤對象追蹤句子,因爲他們需要一個接一個地說。跟蹤對象在Word Online中投擲錯誤

當嘗試通過加載和訪問'font.color'屬性來嘗試更改句子的字體顏色(突出顯示時正在說出)時,就會出現此問題。這將工作在桌面上,但會引發以下錯誤在線:

調試信息:{「代碼」:「GeneralException」,「消息」:「無法讀取屬性空的‘走出去’」,「errorLocation」 :「Range._onAccess」}

下面是最少的代碼來重現問題:

... 
var sentences; 
... 

Word.run(function (context) { 
    var selectedSentence = context.document.getSelection().getTextRanges([".", "!", "?"]); 

    context.load(selectedSentence) 

    return context.sync().then(function() { 

     sentences = selectedSentence.items[0].getRange() 
     .expandTo(context.document.body.paragraphs.getLast().getRange("end")) 
     .getTextRanges([".", "!", "?"]); 

     context.load(sentences); 
     context.trackedObjects.add(sentences); 

     return context.sync(sentences); 
    }) 
}).then(function (sentences) { 

    sentences.context.load(sentences, 'font'); 
    return sentences.context.sync().then(function() { 
     sentences.items[0].font.color = "#2E86C1"; 
    }) 
    .then(sentences.context.sync) 

}).catch(errorHandler); 

如果你只是嘗試直接訪問它的誤差也將產生:

sentences.items[0].font.color = "#2E86C1"; 
sentences.context.sync(); 

回答

1

當代碼在桌面上運行但Office Online失敗時,特別是如果錯誤是關於空對象的,那麼問題通常是破壞的承諾鏈。在桌面上,加載項和Word主機之間的往返是本地的;所以asnyc方法很快就完成了。在這種情況下,即使存在違約承諾鏈,他們也可能會按照所需的順序完成。但是對於Office Online,這些方法需要花費較長時間才能運行,並且如果鏈條中斷,那麼稍後的某些方法可能會在早期方法完成之前完成。

由於您在「.then」之前是否放置換行符,有時您調用context.sync(),但您只是在某個時間引用context.sync時不一致, )。但我認爲一個破碎的承諾鏈是你的問題的原因。

此外,您的then(function (sentences) { ...代碼在Word.run結束後運行。我不認爲你打算這樣做,是嗎?你不想在Word.run中使用這段代碼嗎?

編輯:一位微軟工程師嘗試了以下版本,並表示它在Word Online中工作時,按順序調用這兩個部分。這表明你的代碼的第二部分必須在Word.run中,儘管它不必與第一部分是相同的Word.run。

1部分:

Word.run(function (context) { 
     var selectedSentence = context.document.getSelection().getTextRanges([".", "!", "?"]); 
     context.load(selectedSentence); 

     return context.sync().then(function() { 
      sentences = selectedSentence.items[0].getRange() 
      .expandTo(context.document.body.paragraphs.getLast().getRange("end")) 
      .getTextRanges([".", "!", "?"]); 

      context.load(sentences); 
      context.trackedObjects.add(sentences); 

      return context.sync(sentences); 
     }) 
    }); 

第2部分:

Word.run(sentences, function(ctx){ 
     sentences.load('font'); 
     return ctx.sync().then(function(){ 
      sentences.items[0].font.color = "#2E86C1"; 
      return ctx.sync(); 
     }); 
    }); 
+0

這是故意這是一個Word.Run之外,作爲在用例中,我希望'Word.Run'的執行在下一句話被使用之前完成(並訪問它的字體屬性),因此爲什麼我使用了跟蹤對象,因此我可以在其外部使用'句子'。上面的代碼只顯示了一個正在使用的單個句子,但我實際上使用了speech.onend和callback來遍歷每個句子。 – Daniel

+0

@Daniel參見我的編輯與微軟工程師的代碼。 –

0

我想你可以解決你的情況不跟蹤對象,它真的沒有必要,這只是關於使用運行範圍的集合承諾。看看這個替代方案:(我加入一個計時器,你可以用它來調整你要多少時間,突出每一個句子)

function highlightSentences() { 
 
    Word.run(function (context) { 
 
     var myPars = context.document.body.paragraphs; 
 
     context.load(myPars); 
 
     return context.sync() 
 
      .then(function() { 
 
       var myWords = myPars.items[0].split([".","!","?"], true /*used to trim delimiters*/, true /* used to trim spaces */); 
 
       context.load(myWords, { expand: 'font' }); 
 
       return context.sync() 
 
        .then(function() { 
 
         return forEach(myWords, function (item, i) { 
 
          if (i >= 1) { 
 
           myWords.items[i - 1].font.highlightColor = "#FFFFFF"; 
 
          } 
 
          myWords.items[i].font.highlightColor = "#FFFF00"; 
 
          return createTimerPromise(1000).then(context.sync); 
 
         }) 
 
        }) 
 
      }) 
 
    }) 
 
     .catch(OfficeHelpers.Utilities.log); 
 

 
    function createTimerPromise(ms) { 
 
     return new OfficeExtension.Promise(function (resolve) { 
 
      setTimeout(resolve, ms); 
 
     }) 
 
    } 
 

 
    function forEach(collection, handler) { 
 
     var promise = new OfficeExtension.Promise(function (resolve) { resolve(); }); 
 
     collection.items.forEach(function (item, index) { 
 
      promise = promise.then(function() { 
 
       return handler(item, index); 
 
      }) 
 
     }); 
 
     return promise; 
 
    } 
 
}