2017-04-15 125 views
5

我正在嘗試構建一個帶草稿js的contentEditor。這個功能的確是從像Facebook這樣的URL中提取數據。但我堅持這部分。回叫不起作用。回調不在Ajax請求中工作?

首先我包裹着我的狀態compositeDecorator篩選

constructor(props) { 
    super(props); 
    const compositeDecorator = new CompositeDecorator([ 
     .... { 
      strategy: linkStrategy, 
      component: decorateComponentWithProps(linkComp, { 
       passit 
      }) 
     } 
     .... 
    ]); 
} 
// This is my strategy 
function linkStrategy(contentBlock, callback, contentState) { 
    findLinkInText(LINK_REGEX, contentBlock, callback) 
} 

function findLinkInText(regex, contentBlock, callback) { 
    const text = contentBlock.getText(); 
    let matchArr, start; 
    if ((matchArr = regex.exec(text)) !== null) { 
     start = matchArr.index; 
     let URL = matchArr[0]; 
     console.log(URL); 
     axios.post('/url', { 
      url: URL 
     }).then(response => { 
      passit = response.data 
      //not working 
      callback(start, start + URL.length) 
     }) 
     //working 
     callback(start, start + URL.length) 
    } 
} 

如果回調將無法正常工作,該組件將不會呈現.. 我不知道這是一個基本的JavaScript問題。但事情是我想從我的服務器獲取URL數據,我必須通過道具傳遞數據到我的組件並呈現它。

更新答案

function findLinkInText(regex, contentBlock, callback) { 
    const text = contentBlock.getText(); 
    let matchArr, start; 
    if ((matchArr = regex.exec(text)) !== null) { 
     start = matchArr.index; 
     let url = matchArr[0]; 
     axios.post('/url', { 
      url: URL 
     }).then(response => { 
      passit = response.data 
      handleWithAxiosCallBack(start, start + matchArr[0].length, callback) 
     }).catch(err => console.log(err)) 
    } 
} 


function handleWithAxiosCallBack(start, startLength, callback) { 
    console.log(callback); //Spits out the function But Not working 
    callback(start, startLength) 
} 
+0

從你的例子我看不出你是如何將回調傳遞給'linkStrategy'的。請發佈更多關於'strategy:linkStrategy'的詳細信息 –

+0

先生,從LinkStrategy我將回調傳遞給其他函數,我從那裏找到url匹配回調將被執行@MaximShoustin – Nane

+0

@Nane - 你的passit變量填充了'passit = response。 data'。你可以在'console.log'中檢查。 –

回答

1

顯示的下面描述的技術將幫助你實現你期望的行爲。

爲什麼您的解決方案無效:callback需要執行的所需操作未執行的原因是因爲draft預計callback被稱爲同步。由於您使用的是async函數(axios api調用),並且異步調用callback不起作用。

解決方案:這可能不是一個有效的解決方案,但可以完成工作。簡而言之,您所要做的就是將axios調用的結果存儲在一個變量中(暫時),然後爲您的editor觸發re-render,提前檢索結果存儲並使用它調用回調。

我跟着根據這個例子here。假設您將編輯器狀態存儲在組件的狀態中。以下是您可能需要根據您的需求實施的僞代碼。

假設您的組件狀態如下所示,其中包含Editor的狀態。

constructor(props){ 
super(props); 
// .. your composite decorators 

// this is your component state holding editors state 
this.state = { 
    editorState: EditorState.createWithContent(..) 
} 

// use this to temporarily store the results from axios. 
this.tempResults = {}; 

} 

假設您正在將您的Editor渲染爲如下所示。請注意0​​。這裏的編輯參考信息存儲在組件的editor變量中,您可以稍後訪問該變量。使用字符串作爲參考將工作,但這是推薦的方式來存儲參考。

<Editor 
    ref={ (editor) => this.editor } 
    editorState={this.state.editorState} 
    onChange={this.onChange} 
    // ...your props 
/> 

在你的組件中,編寫一個函數來用currentState更新編輯器,它將強制re-render。確保此功能綁定到您的組件,以便我們獲得正確的this(上下文)。

forceRenderEditor =() => { 
    this.editor.update(this.state.editorState); 
} 

在您的findLinkInText函數中執行以下操作。

首先確保它(findLinkInText)綁定到您的組件,所以我們得到正確的this。你可以使用箭頭函數來做到這一點,或者在組件構造函數中綁定它。

其次,檢查如果我們有結果爲url已經在tempResults 這是我們在組件的構造函數中聲明。如果我們有一個,然後用適當的參數立即調用回調。

如果我們還沒有結果,請撥打電話並將結果存儲在tempResults中。在存儲之後,請調用已定義的this.forceRenderEditor方法,該方法將調用草稿進行重新檢查,並且這次由於我們已將結果存儲在tempResults中,因此將調用回調並進行適當的更改。

function findLinkInText(regex, contentBlock, callback) { 
const text = contentBlock.getText(); 
let matchArr, start; 
if ((matchArr = regex.exec(text)) !== null) { 
    start = matchArr.index; 
    let URL = matchArr[0]; 
    console.log(URL); 

    // do we have the result already,?? 
    // call the callback based on the result. 
    if(this.tempResults[url]) { 
     // make the computations and call the callback() with necessary args 
    } else { 
    // if we don't have a result, call the api 
     axios.post('/url', { 
     url: URL 
     }).then(response => { 
     this.tempResults[url] = response.data; 
     this.forceRenderEditor(); 
     // store the result in this.tempResults and 
     // then call the this.forceRenderEditor 
     // You might need to debounce the forceRenderEditor function 
     }) 
    } 
} 
} 

注:

  1. 你必須確定是否需要清除tempResults。如果是這樣,你需要在適當的地方執行它的邏輯。
  2. 要存儲tempResults,您可以使用名爲memoization的技術。上面描述的是一個簡單的。
  3. 由於您的結果被記錄下來,如果axios api調用結果不會因相同的輸入而改變,這可能對您有利。對於相同的查詢,您可能不必再次點擊api。
  4. 您存儲在tempResults中的數據應該是來自api調用的響應,或者您可以從中確定需要傳遞給callback的參數。
  5. 我想,你可能需要debounceforceRenderEditor方法來避免重複更新,如果有很多API被調用的每個渲染。
  6. 最後,我找不到draft使用或暗示async回調的地方。如果他們支持/需要這樣的功能,您可能需要與圖書館的團隊進行覈對。 (如果需要進行更改,提高公關,如果他們的球隊都確定了一個。)

更新

要綁定您可以在組件中移動的功能,並把它寫下面的方式。

linkStrategy = (contentBlock, callback, contentState) => { 
    this.findLinkInText(LINK_REGEX, contentBlock, callback) 
} 


findLinkInText = (...args) => { 
} 

而且在構造函數,你可以這樣調用

const compositeDecorator = new CompositeDecorator([ 
    .... { 
     strategy: this.linkStrategy, 
     component: decorateComponentWithProps(linkComp, { 
      passit 
     }) 
    } 
    .... 
]); 
} 

或者,如果你想重用跨多個組件功能,那麼你可以在下面的方式綁定。但要確保在所有的共享組件使用相同的state(或使用回調定義自定義狀態)

你的構造會像

const compositeDecorator = new CompositeDecorator([ 
    .... { 
     strategy: linkStrategy.bind(this), 
     component: decorateComponentWithProps(linkComp, { 
      passit 
     }) 
    } 
    .... 
]); 
} 

你的鏈接策略會是這樣

function linkStrategy(contentBlock, callback, contentState) { 
    findLinkInText.call(this,LINK_REGEX, contentBlock, callback); 
} 

您可以使用上述任一方法來綁定您的功能。

+0

您的解決方案有點工作但它引發錯誤像這樣** TypeError:_this4.forceRenderEditor不是一個函數** – Nane

+0

您需要綁定'findLinkInText'與組件。或者你可以使用箭頭功能來做到這一點。發生此錯誤是因爲'findLinkInText'與您的組件不在同一個上下文中。 – Panther

+0

對不起,我不擅長這我已經嘗試了很多你可以用我的問題展示示例.. @ Panther – Nane

-1

假定其他一切工作,我希望更多的東西下面是什麼。我沒有設置使用Axios,所以我實際上不能測試它。

// I made these global variables because you are trying to use them 
// in both the .post and the .then 
var start; // global variable 
var URL // global variable 
function processResponse (aStart, aStartURL, passit) { 
    // do something with the reponse data 
} 

function findLinkInText(regex, contentBlock) { 
    const text = contentBlock.getText(); 
    let matchArr; 
    if((matchArr = regex.exec(text)) !== null){ 
     start = matchArr.index; 
     // renamed because it is not the url, its data passed to the server 
     URL = matchArr[0]; 
     console.log(URL); 
     axios.post('/url',{url:URL}).then(response => { 
      passit = response.data; 
      processResponse (start, start + URL.length, passit) 
     }).catch(function (error) { 
      console.log(error); 
     }); 
    } 
} 
+0

沒有運氣不工作 – Nane

+0

是當時被稱爲?被稱爲捕獲? – Bindrid

+0

查看帖子我更新了代碼隨着你的解決方案仍然無法正常工作... – Nane

-1

注意,「愛可信取決於本地ES6承諾實施的支持。如果您的環境不支持ES6的承諾,你可以填充工具」。這意味着這不適用於所有瀏覽器。 (我無法得到它在IE 11的工作後也包括在這裏推薦包括https://github.com/stefanpenner/es6-promise

這裏是我的代碼,我沒有在邊緣得到工作:

  axios(
       { 
        method: 'post', 
        url: '/wsService.asmx/GetDTDataSerializedList', 
        data: { parameters: 'one' }, 
        callback: function() { alert() } 
       }) 
        .then(response =>{ 
         response.config.callback(); 

         console.log(response); 
        }) 
        .catch(function (error) { 
         console.log(error); 
        }); 
      }); 

有了,我相應地改變你的代碼下面

 function findLinkInText(regex, contentBlock, callback) { 
      const text = contentBlock.getText(); 
      let matchArr, start; 
      if ((matchArr = regex.exec(text)) !== null) { 
       start = matchArr.index; 
       var URL = matchArr[0]; 
       console.log(URL); 

       // I am putting the parameters used to make the call in a JSON object to be used in the "then" 
       var myparameters = { myCallback: callback, URL: URL, start: start }; 

       axios({ 
        method:post, 
        url:'/url', 
        data: { url: URL }, 
        // note that i am attaching the callback to be carrired through 
        myParameters: myparameters 
       }).then(response => { 
        // This section is the callback generated by the post request. 
        // it cannot see anything unless they declared globally or attached to the request and passed through 
        // which is what i did. 
        passit = response.data 
        var s = response.config.myParameters.start; 
        var u = response.config.myParameters.URL 
        response.config.myParameters.myCallback(s, s + u.length) 
       }) 

      } 
     } 
+0

再次沒有運氣先生,我找不到任何線索! – Nane

+0

解釋沒有運氣。它調試了任何調試器線? – Bindrid

+0

後處理WithAxiosCallBack什麼都沒有發生 – Nane