Javascript承诺无法按预期工作

时间:2017-10-25 13:13:50

标签: javascript ecmascript-6 es6-promise

我在这里宣布了我的承诺。

   const fetchmessage= new Promise(
            (resolve,reject)=>{
              this.props.authStore.verifyLocalToken();
              console.log("VLT Resolve");
              resolve("Completed");
            }
            );

          fetchmessage.then(this.props.inboxStore.inboxMessageFetch(mobileNumber,firebaseToken));

以下是我的 verifyLocalToken 代码

   verifyLocalToken() {
    console.log("VerifyLT - Start");
        fetch('http://xxx.xxx.xxx.xxx:8000/api/VerifyLocalToken', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: `mobileNumber=${this.mobileNumber}&key=${this.key}`
        }).then((response) => response.json()).then(
            (responseJson) => {
                console.log("http request v l t --", responseJson);
                this.firebaseToken = responseJson.firebaseToken;
            }).catch(
            (error) => {
                console.error(error);
            }
        )
        console.log("VerifyLT - Stop");

}

以下是我的 inboxMessageFetch 代码

inboxMessageFetch(mobileNumber,firebaseToken) {
        console.log("InboxFetch  --", `${mobileNumber}/inbox`,firebaseToken);

            firebase.database().ref(`${mobileNumber}/inbox`)
                .on('value', snapshot => {
                    console.log('FB', snapshot.val());
                })
    }

输出类似于Console Log

不应该'吨 http request vlt 出现在 InboxFetch - 8891468710 / inbox undefined 之前,因为HTTP请求属于承诺而且我们要求在获取HTTP请求后运行收件箱?

如何重构代码并确保完成HTTP请求,然后调用收件箱提取功能?

3 个答案:

答案 0 :(得分:5)

这里有几个问题。

  1. 该行

    fetchmessage.then(this.props.inboxStore.inboxMessageFetch(mobileNumber,firebaseToken));
    

    ... 调用 this.props.inboxStore.inboxMessageFetch(mobileNumber,firebaseToken)并将其返回值传递到then,与foo(bar()) 调用完全相同 {{1}然后将其返回值传递给bar。你可能想传入一个函数,例如

    foo
  2. 在继续执行fetchmessage.then(() => this.props.inboxStore.inboxMessageFetch(mobileNumber,firebaseToken)); 之前,您还没有等待verifyLocalToken的异步工作完成。

  3. (与#2相关)fetchmessage没有为调用者提供任何方式来知道它的工作已经完成;它需要回复承诺。

  4. (与#2&#3相关)您已经verifyLocalToken中有来自fetch的承诺;所以没有必要创建一个保存在verifyLocalToken中的新承诺。只要您有承诺,请使用fetchmessage,请勿使用then反模式。

  5. new Promise对我来说听起来像是一个函数名,但是在你的代码中,它是一个接收promise而不是函数的变量。

  6. 以下是这些内容的大致内容(请注意fetchmessage条评论):

    ***

    然后verifyLocalToken() { console.log("VerifyLT - Start"); // *** Return the promise from `then` return fetch('http://xxx.xxx.xxx.xxx:8000/api/VerifyLocalToken', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `mobileNumber=${this.mobileNumber}&key=${this.key}` }).then((response) => response.json()).then( (responseJson) => { console.log("http request v l t --", responseJson); this.firebaseToken = responseJson.firebaseToken; }).catch( (error) => { console.error(error); // *** You're converting failure to success // with `undefined` here, which isn't // a good idea. Re-throw the error. throw error; }) // *** If you want to show something when this finishes, do it // in a `then` handler ).then(value => { console.log("VerifyLT - Stop"); return value; }); }

    fetchmessage

    ...如果您想将呼叫分开到const fetchmessage = this.props.authStore.verifyLocalToken() .then(value => { console.log("VLT Resolve"); return "Completed"; // *** Really convert the value to completed? });

    then

    这是您需要做的草图,意味着直接复制和粘贴。仔细考虑变化并在必要时应用它们。

    请记住,promises是一个管道,每个处理程序都会在值经过时对其进行转换。

答案 1 :(得分:2)

      fetchmessage.then(this.props.inboxStore.inboxMessageFetch(mobileNumber,firebaseToken));

此代码直接调用inboxMessageFetch函数而不是等待then。我认为正确的代码是

fetchmessage.then(() =>      
    this.props.inboxStore.inboxMessageFetch(mobileNumber,firebaseToken);
)

答案 2 :(得分:2)

您不需要制定新的承诺,但是您需要从您的方法返回承诺,您的verifyLocalToken方法应该如下所示

 verifyLocalToken() {
    return fetch('http://xxx.xxx.xxx.xxx:8000/api/VerifyLocalToken', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: `mobileNumber=${this.mobileNumber}&key=${this.key}`
        }).then((response) => response.json()).then(
            (responseJson) => {
                console.log("http request v l t --", responseJson);
                this.firebaseToken = responseJson.firebaseToken;
            }).catch(
            (error) => {
                console.error(error);
            }
        )
        console.log("VerifyLT - Stop");

}

然后你可以这样做

const fetchmessage = this.props.authStore.verifyLocalToken();
fetchmessage.then(() => {
    this.props.inboxStore.inboxMessageFetch(mobileNumber,firebaseToken));
}