gpt4 book ai didi

javascript - 在 promise 调用完成之前设置状态

转载 作者:行者123 更新时间:2023-12-03 01:24:19 24 4
gpt4 key购买 nike

正如标题所示,我正在尝试使用 promise 来设置我的 react 组件的状态。很简单,对吧?也许不会。当我尝试在 Promise 中进行后续的 ajax 调用时,问题就出现了。

代码如下。正如您所看到的,我正在尝试映射我返回的数据并创建一个新对象。在创建该对象时,还有另一个 promise 调用,该调用应该设置其中一个字段。所有这些都可以正常工作,但是状态是在第二个 promise 完成之前设置的,并且该字段对我不可用。

我尝试使用 async/await 让它等待调用完成,但这种方法也没有成功。

如果您有任何建议,我们将不胜感激。

我正在 ComponentDidMount 方法中进行调用:

public componentDidMount(): void {
this._spApiService
.getListItems(this.props.context, "Company News")
.then((spNewsStories: SpNewsStory[]) => {
return spNewsStories.map((newsStory: SpNewsStory) => {
return new AdwNewsStory(newsStory, this.props.context);
});
})
.then((adwNewsStories: AdwNewsStory[]) => {
this.setState({
topStories: adwNewsStories,
});
});
}

这是进行第二个 ajax 调用的 AdwNewStory 类:

import { SpNewsStory } from "./SpNewsStory";
import { ISpApiService } from "../../interfaces/ISpApiService";
import SpApiService from "../../services/SpApiService";
import { WebPartContext } from "../../../node_modules/@microsoft/sp-webpart-
base";
import { SpAttachment } from "../SpAttachment";
import IEnvironmentService from "../../interfaces/IEnvironmentService";
import EnvironmentService from "../../services/EnvironmentService";
import { IAdwDateTimeService } from "../../interfaces/IAdwDateTimeService";
import AdwDateTimeService from "../../services/AdwDateTimeService";

class AdwNewsStory {
public id: number;
public title: string;
public publishDate: string;
public storySummary: string;
public storyLink: string;
public windowTarget: string;
public imageUrl: string;
public imageAlternativeText: string;
public attachments: boolean;

private _spApiService: ISpApiService;
private _context: WebPartContext;
private _environmentService: IEnvironmentService;
private _adwDateTimeService: IAdwDateTimeService;

constructor(spNewsStory: SpNewsStory, context?: WebPartContext) {
this._spApiService = new SpApiService();
this._context = context;
this._environmentService = new EnvironmentService();
this._adwDateTimeService = new AdwDateTimeService();
this.buildAdwNewsStory(spNewsStory);
}

private buildAdwNewsStory = (spNewsStory: SpNewsStory): void => {
this.id = spNewsStory.Id;
this.title = spNewsStory.Title;
this.publishDate = this.setPublishDate(spNewsStory.PublishDate);
this.storySummary = spNewsStory.StorySummary;
this.storyLink = spNewsStory.Link.Description;
this.windowTarget = spNewsStory.WindowTarget;
this.imageAlternativeText = spNewsStory.ImageAlternateText;
this.attachments = spNewsStory.Attachments;
if (this.attachments) {
this.setImageUrl();
}
};

private setImageUrl = (): void => {
this._spApiService.getListItemAttachments(this._context, "Company News", this.id).then(attachments => {
const siteUrl: string = this._environmentService.getSiteUrl();
const attchmentUrl: string = `${siteUrl}/Lists/Company%20News/Attachments/${this.id}/${attachments[0].FileName}`;
this.imageUrl = attchmentUrl;
});
};

private setPublishDate = (dateString: string) => {
const publishDate: Date = new Date(dateString);
return `${this._adwDateTimeService.getMonthName(publishDate.getMonth())} ${publishDate.getDate()}, ${publishDate.getFullYear()}`;
};
}

export default AdwNewsStory;

最佳答案

这里有几个问题。首先:

private setImageUrl = (): void => {
// You aren't returning this promise here, so there's no way for
// calling code to get notified when the promise resolves
this._spApiService.getListItemAttachments(this._context, "Company News", this.id).then(attachments => {
const siteUrl: string = this._environmentService.getSiteUrl();
const attchmentUrl: string = `${siteUrl}/Lists/Company%20News/Attachments/${this.id}/${attachments[0].FileName}`;
this.imageUrl = attchmentUrl;
});
};

然而,更大的问题是您从构造函数中调用该方法。您确实不希望构造函数进行异步调用。虽然没有技术理由不这样做,但实际上没有办法将该 promise 返回给调用者。这会导致像您遇到的那样的错误。

我建议将 buildAdwNewsStory() 方法移出构造函数,并单独调用它,因为它涉及异步调用。

class AdwNewsStory {
// ... fields...
constructor(context?: WebPartContext) {
this._spApiService = new SpApiService();
this._context = context;
this._environmentService = new EnvironmentService();
this._adwDateTimeService = new AdwDateTimeService();
}

public buildAdwNewsStory(spNewsStory: SpNewsStory): Promise<void> {
this.id = spNewsStory.Id;
this.title = spNewsStory.Title;
this.publishDate = this.setPublishDate(spNewsStory.PublishDate);
this.storySummary = spNewsStory.StorySummary;
this.storyLink = spNewsStory.Link.Description;
this.windowTarget = spNewsStory.WindowTarget;
this.imageAlternativeText = spNewsStory.ImageAlternateText;
this.attachments = spNewsStory.Attachments;
if (this.attachments) {
return this.setImageUrl();
} else {
return Promise.resolve();
}
}
...
private setImageUrl() {
return this._spApiService.getListItemAttachments(this._context, "Company News", this.id)
.then(attachments => {
const siteUrl: string = this._environmentService.getSiteUrl();
const attchmentUrl: string = `${siteUrl}/Lists/Company%20News/Attachments/${this.id}/${attachments[0].FileName}`;
this.imageUrl = attchmentUrl;
});
}
}

然后从您的componentDidMount:

public componentDidMount(): void {
this._spApiService
.getListItems(this.props.context, "Company News")
.then((spNewsStories: SpNewsStory[]) =>
spNewsStories.map((newsStory: SpNewsStory) => {
var story = new AdwNewsStory(this.props.context);
return story.buildAdwNewsStory(newsStory);
})
)
.then((adwNewsStories: AdwNewsStory[]) => {
this.setState({
topStories: adwNewsStories,
});
});
}

顺便说一句,如果您转向 async/await 而不是直接使用 Promise 方法 (.然后/.catch)

关于javascript - 在 promise 调用完成之前设置状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51617019/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com