我收到此错误
TypeError: Cannot read property 'slice' of undefined
at Object.renderResults (searchView.js:93)
at _callee$ (index.js:85)
at tryCatch (runtime.js:65)
at Generator.invoke [as _invoke] (runtime.js:303)
at Generator.prototype.(:8081/anonymous function) [as next] (webpack:///./node_modules/babel-polyfill/node_modules/regenerator-runtime/runtime.js?:117:21)
at step (index.js:41)
at eval (index.js:41)
在我的项目的搜索栏中搜索“披萨”后,这是我的github存储库:https://github.com/damianjnc/finalforkify
我相信这段代码可能存在错误:
export const renderResults = (recipes, page = 1, resPerPage = 10) => {
// render results of currente page
const start = (page - 1) * resPerPage;
const end = page * resPerPage;
recipes.slice(start, end).forEach(recipe => renderRecipe(recipe));
// render pagination buttons
renderButtons(page, recipes.length, resPerPage);
};
在文件searchView.js中:
import { elements } from './base';
export const getInput = () => elements.searchInput.value;
export const clearInput = () => {
elements.searchInput.value = '';
};
export const clearResults = () => {
elements.searchResList.innerHTML = '';
elements.searchResPages.innerHTML = '';
};
export const highlightSelected = id => {
const resultsArr = Array.from(document.querySelectorAll('.results__link'));
resultsArr.forEach(el => {
el.classList.remove('results__link--active');
});
document.querySelector(`.results__link[href*="${id}"]`).classList.add('results__link--active');
};
/*
// 'Pasta with tomato and spinach'
acc: 0 / acc + cur.length = 5 / newTitle = ['Pasta']
acc: 5 / acc + cur.length = 9 / newTitle = ['Pasta', 'with']
acc: 9 / acc + cur.length = 15 / newTitle = ['Pasta', 'with', 'tomato']
acc: 15 / acc + cur.length = 18 / newTitle = ['Pasta', 'with', 'tomato']
acc: 18 / acc + cur.length = 24 / newTitle = ['Pasta', 'with', 'tomato']
*/
export const limitRecipeTitle = (title, limit = 17) => {
const newTitle = [];
if (title.length > limit) {
title.split(' ').reduce((acc, cur) => {
if (acc + cur.length <= limit) {
newTitle.push(cur);
}
return acc + cur.length;
}, 0);
// return the result
return `${newTitle.join(' ')} ...`;
}
return title;
}
const renderRecipe = recipe => {
const markup = `
<li>
<a class="results__link" href="#${recipe.recipe_id}">
<figure class="results__fig">
<img src="${recipe.image_url}" alt="${recipe.title}">
</figure>
<div class="results__data">
<h4 class="results__name">${limitRecipeTitle(recipe.title)}</h4>
<p class="results__author">${recipe.publisher}</p>
</div>
</a>
</li>
`;
elements.searchResList.insertAdjacentHTML('beforeend', markup);
};
// type: 'prev' or 'next'
const createButton = (page, type) => `
<button class="btn-inline results__btn--${type}" data-goto=${type === 'prev' ? page - 1 : page + 1}>
<span>Page ${type === 'prev' ? page - 1 : page + 1}</span>
<svg class="search__icon">
<use href="img/icons.svg#icon-triangle-${type === 'prev' ? 'left' : 'right'}"></use>
</svg>
</button>
`;
const renderButtons = (page, numResults, resPerPage) => {
const pages = Math.ceil(numResults / resPerPage);
let button;
if (page === 1 && pages > 1) {
// Only button to go to next page
button = createButton(page, 'next');
} else if (page < pages) {
// Both buttons
button = `
${createButton(page, 'prev')}
${createButton(page, 'next')}
`;
} else if (page === pages && pages > 1) {
// Only button to go to prev page
button = createButton(page, 'prev');
}
elements.searchResPages.insertAdjacentHTML('afterbegin', button);
};
export const renderResults = (recipes, page = 1, resPerPage = 10) => {
// render results of currente page
const start = (page - 1) * resPerPage;
const end = page * resPerPage;
recipes.slice(start, end).forEach(recipe => renderRecipe(recipe));
// render pagination buttons
renderButtons(page, recipes.length, resPerPage);
};
调用renderResults
函数的代码在index.js
文件中。这是代码的一部分:
/**
* SEARCH CONTROLLER
*/
const controlSearch = async () => {
// 1) Get query from view
const query = searchView.getInput();
if (query) {
// 2) New search object and add to state
state.search = new Search(query);
// 3) Prepare UI for results
searchView.clearInput();
searchView.clearResults();
renderLoader(elements.searchRes);
try {
// 4) Search for recipes
await state.search.getResults();
// 5) Render results on UI
clearLoader();
searchView.renderResults(state.search.result);
} catch (err) {
console.log(err);
alert('Something wrong with the search...');
clearLoader();
}
}
}
elements.searchForm.addEventListener('submit', e => {
e.preventDefault();
controlSearch();
});
和完整的index.js文件:
import Search from './models/Search';
import Recipe from './models/Recipe';
import List from './models/List';
import Likes from './models/Likes';
import * as searchView from './views/searchView';
import * as recipeView from './views/recipeView';
import * as listView from './views/listView';
import * as likesView from './views/likesView';
import { elements, renderLoader, clearLoader } from './views/base';
/** Global state of the app
* - Search object
* - Current recipe object
* - Shopping list object
* - Liked recipes
*/
const state = {};
/**
* SEARCH CONTROLLER
*/
const controlSearch = async () => {
// 1) Get query from view
const query = searchView.getInput();
if (query) {
// 2) New search object and add to state
state.search = new Search(query);
// 3) Prepare UI for results
searchView.clearInput();
searchView.clearResults();
renderLoader(elements.searchRes);
try {
// 4) Search for recipes
await state.search.getResults();
// 5) Render results on UI
clearLoader();
searchView.renderResults(state.search.result);
} catch (err) {
console.log(err);
alert('Something wrong with the search...');
clearLoader();
}
}
}
elements.searchForm.addEventListener('submit', e => {
e.preventDefault();
controlSearch();
});
elements.searchResPages.addEventListener('click', e => {
const btn = e.target.closest('.btn-inline');
if (btn) {
const goToPage = parseInt(btn.dataset.goto, 10);
searchView.clearResults();
searchView.renderResults(state.search.result, goToPage);
}
});
/**
* RECIPE CONTROLLER
*/
const controlRecipe = async () => {
// Get ID from url
const id = window.location.hash.replace('#', '');
if (id) {
// Prepare UI for changes
recipeView.clearRecipe();
renderLoader(elements.recipe);
// Highlight selected search item
if (state.search) searchView.highlightSelected(id);
// Create new recipe object
state.recipe = new Recipe(id);
try {
// Get recipe data and parse ingredients
await state.recipe.getRecipe();
state.recipe.parseIngredients();
// Calculate servings and time
state.recipe.calcTime();
state.recipe.calcServings();
// Render recipe
clearLoader();
recipeView.renderRecipe(
state.recipe,
state.likes.isLiked(id)
);
} catch (err) {
console.log(err);
alert('Error processing recipe!');
}
}
};
['hashchange', 'load'].forEach(event => window.addEventListener(event, controlRecipe));
/**
* LIST CONTROLLER
*/
const controlList = () => {
// Create a new list IF there in none yet
if (!state.list) state.list = new List();
// Add each ingredient to the list and UI
state.recipe.ingredients.forEach(el => {
const item = state.list.addItem(el.count, el.unit, el.ingredient);
listView.renderItem(item);
});
}
// Handle delete and update list item events
elements.shopping.addEventListener('click', e => {
const id = e.target.closest('.shopping__item').dataset.itemid;
// Handle the delete button
if (e.target.matches('.shopping__delete, .shopping__delete *')) {
// Delete from state
state.list.deleteItem(id);
// Delete from UI
listView.deleteItem(id);
// Handle the count update
} else if (e.target.matches('.shopping__count-value')) {
const val = parseFloat(e.target.value, 10);
state.list.updateCount(id, val);
}
});
/**
* LIKE CONTROLLER
*/
const controlLike = () => {
if (!state.likes) state.likes = new Likes();
const currentID = state.recipe.id;
// User has NOT yet liked current recipe
if (!state.likes.isLiked(currentID)) {
// Add like to the state
const newLike = state.likes.addLike(
currentID,
state.recipe.title,
state.recipe.author,
state.recipe.img
);
// Toggle the like button
likesView.toggleLikeBtn(true);
// Add like to UI list
likesView.renderLike(newLike);
// User HAS liked current recipe
} else {
// Remove like from the state
state.likes.deleteLike(currentID);
// Toggle the like button
likesView.toggleLikeBtn(false);
// Remove like from UI list
likesView.deleteLike(currentID);
}
likesView.toggleLikeMenu(state.likes.getNumLikes());
};
// Restore liked recipes on page load
window.addEventListener('load', () => {
state.likes = new Likes();
// Restore likes
state.likes.readStorage();
// Toggle like menu button
likesView.toggleLikeMenu(state.likes.getNumLikes());
// Render the existing likes
state.likes.likes.forEach(like => likesView.renderLike(like));
});
// Handling recipe button clicks
elements.recipe.addEventListener('click', e => {
if (e.target.matches('.btn-decrease, .btn-decrease *')) {
// Decrease button is clicked
if (state.recipe.servings > 1) {
state.recipe.updateServings('dec');
recipeView.updateServingsIngredients(state.recipe);
}
} else if (e.target.matches('.btn-increase, .btn-increase *')) {
// Increase button is clicked
state.recipe.updateServings('inc');
recipeView.updateServingsIngredients(state.recipe);
} else if (e.target.matches('.recipe__btn--add, .recipe__btn--add *')) {
// Add ingredients to shopping list
controlList();
} else if (e.target.matches('.recipe__love, .recipe__love *')) {
// Like controller
controlLike();
}
});
答案 0 :(得分:1)
我也遇到了同样的错误。
收到此错误后,我知道了数组或与slice()
一起使用的任何对象未定义或为null的情况。
这就是为什么会发生此错误。
response(dd.slice(0, 20));
错误
> Index:103 Uncaught TypeError: Cannot read property 'slice' of
> undefined
> at Object.success (Index:103)
> at fire (jquery-1.12.4.js:3232)
> at Object.fireWith [as resolveWith] (jquery-1.12.4.js:3362)
> at done (jquery-1.12.4.js:9840)
> at XMLHttpRequest.callback (jquery-1.12.4.js:10311)
答案 1 :(得分:0)
我也遇到了同样的错误。
可能是因为您一天的使用量已达到限制,最多只能拨打50个电话。
等待明天或创建另一个帐户并使用新密钥。
对我有用的:)
答案 2 :(得分:-2)
切片适用于字符串,因此请确保dd为字符串或执行dd.toString()。slice(to,from);