2017-04-15 124 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