简体   繁体   English

Javascript 承诺没有按预期工作

[英]The Javascript promise does not work as expected

Here I declared my 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));

The following is my verifyLocalToken code下面是我的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");

}

Following is my inboxMessageFetch code以下是我的inboxMessageFetch代码

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

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

The output is like this输出是这样的控制台日志

Shouldn't http request vlt comes before InboxFetch -- 8891468710/inbox undefined , because HTTP request belongs to the promise and the inbox fetch we asked to run after fetching the HTTP request? http 请求 vlt不应该在InboxFetch之前出现 -- 8891468710/inbox undefined ,因为 HTTP 请求属于我们要求在获取 HTTP 请求后运行的承诺和收件箱获取吗?

How to refactor the code and make sure the HTTP request completed and then call the inbox fetch function?如何重构代码并确保HTTP请求完成,然后调用收件箱提取函数?

There are several issues here.这里有几个问题。

  1. The line线

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

    ... calls this.props.inboxStore.inboxMessageFetch(mobileNumber,firebaseToken) and passes its return value into then , exactly like foo(bar()) calls bar and then passes its return value into foo . ...调用this.props.inboxStore.inboxMessageFetch(mobileNumber,firebaseToken)并将其返回值传递给then ,就像foo(bar())调用bar然后将其返回值传递给foo You probably meant to pass in a function, eg您可能打算传入一个函数,例如

    fetchmessage.then(() => this.props.inboxStore.inboxMessageFetch(mobileNumber,firebaseToken));
  2. You're not waiting for verifyLocalToken 's work, which is asynchronous, to complete before you continue with the execution of fetchmessage .在继续执行fetchmessage之前,您不必等待verifyLocalToken的异步工作完成。

  3. (Related to #2) verifyLocalToken doesn't provide any way for the caller to know it's work is done; (与#2 相关) verifyLocalToken不提供任何方式让调用者知道它的工作已经完成; it needs to return a promise.它需要返回一个承诺。

  4. (Related to #2 & #3) You already have a promise, from fetch , in verifyLocalToken ; (与#2 和#3 相关)您已经有一个承诺,来自fetch ,在verifyLocalToken so there's no need to create a new promise to save in fetchmessage .所以没有必要创建一个新的承诺来保存在fetchmessage Any time you have a promise, use then , don't use the new Promise anti-pattern.任何时候你有一个承诺,使用then ,不要使用new Promise反模式。

  5. fetchmessage sounds like a function name to me, but in your code, it's a variable that will receive a promise, not a function. fetchmessage对我来说听起来像一个函数名,但在你的代码中,它是一个将接收承诺的变量,而不是一个函数。

Here's roughly how that stuff should look (note the *** comments):以下是这些东西的大致外观(注意***注释):

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;
    });
}

Then fetchmessage :然后fetchmessage

const fetchmessage = this.props.authStore.verifyLocalToken()
    .then(value => {
        console.log("VLT Resolve");
        return "Completed"; // *** Really convert the value to completed?
    });

...and if you want to then separate the call to then : ...如果你想那么调用分开, then

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

That's a sketch of what you need to do, not meant to be copied-and-pasted directly.这是您需要做的草图,而不是直接复制和粘贴。 Think the changes through and apply them as necessary.仔细考虑更改并根据需要应用它们。

Remember that promises are a pipeline where each handler gets to transform the value as it goes through.请记住,promise 是一个管道,每个处理程序都可以在其中转换值。

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

This code is directly calling the inboxMessageFetch function and not waiting for the then.这段代码是直接调用inboxMessageFetch函数而不是等待then。 I think the correct code is我认为正确的代码是

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

You don't need to make a new promise, but you do need to return the promises from your methods your verifyLocalToken method should look like this您不需要做出新的承诺,但您确实需要从您的方法中返回承诺,您的 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");

}

Then you can just do this然后你可以这样做

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM