处理承诺异常的问题

Posted

技术标签:

【中文标题】处理承诺异常的问题【英文标题】:Issue with handling promise exceptions 【发布时间】:2021-10-07 02:02:03 【问题描述】:

大家好,我正在尝试使用 javascript 解决问题陈述,该陈述具有一个简单的按钮,可以在其 onclick 中将电影添加到收藏夹。如果电影已经被添加到收藏夹中,该函数应该抛出一个Promise.reject()

因此,addFavourite() 有一些测试用例,并且一些测试用例失败了。你能告诉我为什么吗?我无法更改测试文件,所以我应该在我的代码中更改什么来解决错误?

这是我的addFavourite() 函数。 (注意:allMovies 是所有电影对象的列表):

function addFavourite(searchId) 
  var favMovie = [];
  allMovies.forEach((iterator) => 
    if (iterator.id == searchId) 
      favMovie = iterator;
    
  );
  var movieRepeated = false;
  allFavourites.forEach((iterator) => 
    if (iterator.id == favMovie.id) 
      movieRepeated = true;
    
  );
  if (movieRepeated) 
    return Promise.reject(new Error("Movie repeated!")).then(
      resolved,
      rejected
    );
   else 
    fetch("http://localhost:3000/favourites", 
      method: "POST",
      headers: 
        "content-type": "application/json",
      ,
      body: JSON.stringify(favMovie),
    )
      .then((response) => 
        if (response.ok) 
          return response.json();
        
      )
      .then((addedMovie) => 
        allFavourites.push(addedMovie);
        displayFavs(allFavourites);
        return allFavourites;
      );
  



这些是失败的测试用例:

1.

it('adding of same movie as favourite twice shall be restricted', (done) => 
        fetchMock.get('http://localhost:3000/movies', moviesTestData);
        fetchMock.get('http://localhost:3000/favourites', favouritesTestData);
        fetchMock.post('http://localhost:3000/favourites', moviesTestData[0]);

        script.getMovies()
        .then(() => 
            return script.getFavourites();
        )
        .then(() => 
            return script.addFavourite(476307);
        )
        .catch((err) => 
            expect(err).to.not.equal(null, err);
            expect(err.message).to.equal('Movie is already added to favourites');
            done();
        );
    );

it(`addFavourites() shall hit the correct api with correct data and 
        return correct response`, (done) => 
            fetchMock.get('http://localhost:3000/movies', moviesTestData);
            fetchMock.get('http://localhost:3000/favourites', favouritesTestData);
            fetchMock.post('http://localhost:3000/favourites', moviesTestData[0]);

            script.getMovies()
            .then(() => 
                return script.getFavourites();
            )
            .then(() => 
                return script.addFavourite(476307);
            )
            .then((res) => 
                const lastCallArgs = fetchMock.lastCall();
                expect(lastCallArgs[0]).to.equal('http://localhost:3000/favourites');
                expect(lastCallArgs[1].method).to.equal('POST');
                expect(lastCallArgs[1].body).to.equal(JSON.stringify(moviesTestData[0]));
                favouritesTestData.push(moviesTestData[0]);
                expect(res).to.deep.equal(favouritesTestData);
                expect(document.getElementById('favouritesList').innerhtml)
                .to.include('The Unique Lama');
                done();
            )
            .catch((err) => 
                expect(err).to.equal(null, err);
                done();
            );
    );

这是我得到的错误:

addFavourites() shall hit the correct api with correct data and return correct response:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. 
      at listOnTimeout (internal/timers.js:554:17)
      at processTimers (internal/timers.js:497:7)

【问题讨论】:

您正在测试== favMovie.id,但favMovie 是一个数组并且没有.id 属性?! ".then(resolved, rejected)" - 这闻起来像Promise constructor antipattern!并注意它返回一个始终履行的承诺 a,因为 rejected 处理错误。 您在fetch(…).then(…); 承诺链前面缺少return 我错误地将 favMovie 初始化为数组 []!这是一个对象,应该是 。一旦我遍历所有电影并找到具有相同 id 的对象,它就会存储该对象的值。 另外,我想我需要先了解 Promise 是如何工作的,然后我才能了解这里发生了什么!不过非常感谢。 【参考方案1】:

您可能还需要在 then 主体中调用 done(),因为您没有向测试运行器返回承诺。

【讨论】:

以上是关于处理承诺异常的问题的主要内容,如果未能解决你的问题,请参考以下文章

Try/catch 块和未处理的承诺异常

Node.js 承诺和异步异常

异常被承诺链吞噬

如何跳过导致异常的链式承诺?

使用 Mongoose 处理承诺的问题

Axios 承诺解决/待处理承诺